libdynDwarf is compiling now.
[dyninst.git] / dwarf / src / dwarfExprParser.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include <stack>
32 #include <stdio.h>
33 #include "dyn_regs.h"
34 #include "dwarfExprParser.h"
35 #include "dwarfResult.h"
36 #include "debug_common.h"
37 #include "VariableLocation.h"
38 #include "ProcReader.h"
39 #include "Types.h"
40
41 using namespace std;
42
43 namespace Dyninst {
44 namespace Dwarf {
45
46 bool decodeDwarfExpression(Dwarf_Op * expr,
47         Dwarf_Sword listlen,
48         long int *initialStackValue,
49         VariableLocation &loc,
50         Dyninst::Architecture arch) {
51     SymbolicDwarfResult res(loc, arch);
52     if (!decodeDwarfExpression(expr, listlen, initialStackValue, 
53                 res, arch)) return false;
54     res.val();
55     return true;
56 }
57
58 bool decodeDwarfExpression(Dwarf_Op * expr,
59         Dwarf_Sword listlen,
60         long int *initialStackValue,
61         ProcessReader *reader,
62         Address pc,
63         ::Dwarf * dbg,
64         Dyninst::Architecture arch,
65         MachRegisterVal &end_result) {
66     ConcreteDwarfResult res(reader, arch, pc, dbg);
67     if (!decodeDwarfExpression(expr, listlen, initialStackValue, 
68                 res, arch)) return false;
69     if (res.err()) return false;
70     end_result = res.val();
71     return true;
72 }
73
74 bool decodeDwarfExpression(Dwarf_Op * expr,
75         Dwarf_Sword listlen,
76         long int *initialStackValue,
77         DwarfResult &cons,
78         Dyninst::Architecture arch) {
79     // This is basically a decode passthrough, with the work
80     // being done by the DwarfResult. 
81
82     dwarf_printf("Entry to decodeDwarfExpression\n");
83
84     int addr_width = getArchAddressWidth(arch);
85     if (initialStackValue != NULL) {
86         dwarf_printf("\tInitializing expr stack with 0x%lx\n", initialStackValue);
87         cons.pushUnsignedVal((Dyninst::MachRegisterVal) *initialStackValue);
88     }
89
90     Dwarf_Op *locations = expr;
91     unsigned count = listlen;
92     for ( unsigned int i = 0; i < count; i++ ) 
93     {
94         dwarf_printf("\tAtom %d of %d: val 0x%x\n", i, count, locations[i].atom);
95         /* lit0 - lit31 : the constants 0..31 */
96         if ( DW_OP_lit0 <= locations[i].atom && locations[i].atom <= DW_OP_lit31 ) 
97         {
98             dwarf_printf("\t\t Pushing unsigned val 0x%lx\n", locations[i].atom - DW_OP_lit0);
99             cons.pushUnsignedVal((Dyninst::MachRegisterVal) (locations[i].atom - DW_OP_lit0));
100             continue;
101         }
102
103         /* reg0 - reg31: named registers (not their constants) */
104         if ( DW_OP_reg0 <= locations[i].atom && locations[i].atom <= DW_OP_reg31 ) 
105         {
106             dwarf_printf("\t\t Pushing reg %s\n",MachRegister::DwarfEncToReg(locations[i].atom - DW_OP_reg0,
107                         arch).name().c_str());
108
109             cons.pushReg(MachRegister::DwarfEncToReg(locations[i].atom - DW_OP_reg0,
110                         arch));
111             continue;
112         }
113
114         /* breg0 - breg31: register contents plus an optional offset */
115         if ( DW_OP_breg0 <= locations[i].atom && locations[i].atom <= DW_OP_breg31 ) 
116         {
117             dwarf_printf("\t\t Pushing reg %s + %d\n",MachRegister::DwarfEncToReg(locations[i].atom - DW_OP_reg0,
118                         arch).name().c_str(),
119                     locations[i].number);
120             cons.readReg(MachRegister::DwarfEncToReg(locations[i].atom - DW_OP_breg0,
121                         arch));
122             cons.pushSignedVal((Dyninst::MachRegisterVal) locations[i].number);
123             cons.pushOp(DwarfResult::Add);
124             continue;
125         }
126
127         switch( locations[i].atom ) {
128             // This is the same thing as breg, just with an encoded instead of literal
129             // register.
130             // The register is in number
131             // The offset is in number2
132             case DW_OP_bregx:
133                 dwarf_printf("\t\t Pushing reg %s + %d\n",MachRegister::DwarfEncToReg(locations[i].number,
134                             arch).name().c_str(),
135                         locations[i].number2);
136
137                 cons.readReg(MachRegister::DwarfEncToReg(locations[i].number, arch));
138                 cons.pushSignedVal(locations[i].number2);
139                 cons.pushOp(DwarfResult::Add);
140                 break;
141
142             case DW_OP_regx:
143                 dwarf_printf("\t\t Pushing reg %s\n",MachRegister::DwarfEncToReg(locations[i].number,
144                             arch).name().c_str());
145                 cons.pushReg(MachRegister::DwarfEncToReg(locations[i].number, arch));
146                 break;
147
148             case DW_OP_nop:
149                 dwarf_printf("\t\t NOP\n");
150                 break;
151
152             case DW_OP_addr:
153             case DW_OP_const1u:
154             case DW_OP_const2u:
155             case DW_OP_const4u:
156             case DW_OP_const8u:
157             case DW_OP_constu:
158                 dwarf_printf("\t\t Pushing unsigned 0x%lx\n", locations[i].number);
159                 cons.pushUnsignedVal(locations[i].number);
160                 break;
161
162             case DW_OP_const1s:
163             case DW_OP_const2s:
164             case DW_OP_const4s:
165             case DW_OP_const8s:
166             case DW_OP_consts:
167                 dwarf_printf("\t\t Pushing signed 0x%lx\n", locations[i].number);
168                 cons.pushSignedVal(locations[i].number);
169                 break;
170
171             case DW_OP_fbreg:
172                 dwarf_printf("\t\t Pushing FB + 0x%lx\n", locations[i].number);
173                 cons.pushFrameBase();
174                 cons.pushSignedVal(locations[i].number);
175                 cons.pushOp(DwarfResult::Add);
176                 break;
177
178             case DW_OP_dup: 
179                 dwarf_printf("\t\t Pushing dup\n");
180                 cons.pushOp(DwarfResult::Pick, 0);
181                 break;
182
183             case DW_OP_drop:
184                 dwarf_printf("\t\t Pushing drop\n");
185                 cons.pushOp(DwarfResult::Drop, 0);
186                 break;
187
188             case DW_OP_pick: 
189                 dwarf_printf("\t\t Pushing pick %d\n", locations[i].number);
190                 cons.pushOp(DwarfResult::Pick, locations[i].number);
191                 break;
192
193             case DW_OP_over: 
194                 dwarf_printf("\t\t Pushing pick 1\n");
195                 cons.pushOp(DwarfResult::Pick, 1);
196                 break;
197
198             case DW_OP_swap: 
199                 dwarf_printf("\t\t Pushing swap\n");
200                 cons.pushOp(DwarfResult::Pick, 1);
201                 cons.pushOp(DwarfResult::Drop, 2);
202                 break;
203
204             case DW_OP_rot: 
205                 dwarf_printf("\t\t Pushing rotate\n");
206                 cons.pushOp(DwarfResult::Pick, 2);
207                 cons.pushOp(DwarfResult::Pick, 2);
208                 cons.pushOp(DwarfResult::Drop, 3);
209                 cons.pushOp(DwarfResult::Drop, 3);
210                 break;
211
212             case DW_OP_deref:
213                 dwarf_printf("\t\t Pushing deref %d\n", addr_width);
214                 cons.pushOp(DwarfResult::Deref, addr_width);
215                 break;
216
217             case DW_OP_deref_size:
218                 dwarf_printf("\t\t Pushing deref %d\n", locations[i].number);
219                 cons.pushOp(DwarfResult::Deref, locations[i].number);
220                 break;
221
222             case DW_OP_call_frame_cfa:
223                 // This is a reference to the CFA as computed by stack walking information.
224                 // The current order is:
225                 // Variable: reference frame base (fbreg, above)
226                 // Frame base: reference CFA
227                 // CFA: offset from stack pointer
228                 dwarf_printf("\t\t Pushing CFA\n");
229                 cons.pushCFA();
230                 break;
231
232             case DW_OP_abs:
233                 dwarf_printf("\t\t Pushing abs\n");
234                 cons.pushOp(DwarfResult::Abs);
235                 break;
236
237             case DW_OP_and:
238                 dwarf_printf("\t\t Pushing and\n");
239                 cons.pushOp(DwarfResult::And);
240                 break;
241
242             case DW_OP_div:
243                 dwarf_printf("\t\t Pushing div\n");
244                 cons.pushOp(DwarfResult::Div);
245                 break;
246
247             case DW_OP_minus:
248                 dwarf_printf("\t\t Pushing sub\n");
249                 cons.pushOp(DwarfResult::Sub);
250                 break;
251
252             case DW_OP_mod:
253                 cons.pushOp(DwarfResult::Mod);
254                 break;
255
256             case DW_OP_mul:
257                 cons.pushOp(DwarfResult::Mul);
258                 break;
259
260             case DW_OP_neg:
261                 cons.pushSignedVal(-1);
262                 cons.pushOp(DwarfResult::Mul);
263                 break;
264
265             case DW_OP_not:
266                 cons.pushOp(DwarfResult::Not);
267                 break;
268
269             case DW_OP_or:
270                 cons.pushOp(DwarfResult::Or);
271                 break;
272
273             case DW_OP_plus:
274                 dwarf_printf("\t\t Pushing add\n");
275                 cons.pushOp(DwarfResult::Add);
276                 break;
277
278             case DW_OP_plus_uconst:
279                 dwarf_printf("\t\t Pushing add 0x%x\n", locations[i].number);
280
281                 cons.pushOp(DwarfResult::Add, locations[i].number);
282                 break;
283
284             case DW_OP_shl:
285                 cons.pushOp(DwarfResult::Shl);
286                 break;
287
288             case DW_OP_shr:
289                 cons.pushOp(DwarfResult::Shr);
290                 break;
291
292             case DW_OP_shra:
293                 cons.pushOp(DwarfResult::ShrArith);
294                 break;
295
296             case DW_OP_xor:
297                 cons.pushOp(DwarfResult::Xor);
298                 break;
299
300             case DW_OP_le:
301                 cons.pushOp(DwarfResult::LE);
302                 break;
303
304             case DW_OP_ge:
305                 cons.pushOp(DwarfResult::GE);
306                 break;
307
308             case DW_OP_eq:
309                 cons.pushOp(DwarfResult::Eq);
310                 break;
311
312             case DW_OP_ne:
313                 cons.pushOp(DwarfResult::Neq);
314                 break;
315
316             case DW_OP_lt:
317                 cons.pushOp(DwarfResult::LT);
318                 break;
319
320             case DW_OP_gt:
321                 cons.pushOp(DwarfResult::GT);
322                 break;
323
324             case DW_OP_bra: 
325                 {
326                     // Conditional branch... 
327                     // It needs immediate evaluation so we can continue processing
328                     // the DWARF. 
329                     Dyninst::MachRegisterVal value;
330
331                     if (!cons.eval(value)) {
332                         // Error in dwarf, or we're doing static. I'm not worrying about
333                         // encoding a conditional branch in static eval right now. 
334                         return false;
335                     }
336
337                     if (value == 0) break;
338                     // Do not break; fall through to skip
339                 }
340             case DW_OP_skip: 
341                 {
342                     int bytes = (int)(Dwarf_Sword)locations[i].number;
343                     unsigned int target = (unsigned int) locations[i].offset + bytes;
344
345                     unsigned int j = i;
346                     if ( bytes < 0 ) {
347                         for ( j = i - 1; /*FIXME j >= 0*/; j-- ) {
348                             if ( locations[j].offset == target ) { break; }
349                         } /* end search backward */
350                     } else {
351                         for ( j = i + 1; j < count; j ++ ) {
352                             if ( locations[j].offset == target ) { break; }
353                         } /* end search forward */
354                     } /* end if positive offset */
355
356                     /* Because i will be incremented the next time around the loop. */
357                     i = j - 1; 
358                     break;
359                 }
360             case DW_OP_piece:
361                 // Should detect multiple of these...
362                 continue;
363             default:
364                 return false;
365         } /* end operand switch */
366     } /* end iteration over Dwarf_Op entries. */
367
368     return true;
369 }
370
371 }
372
373 }
374