Assorted bugfixes: don't die on DW_OP_piece, remove unimplemented stream operators...
[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 "common/h/dyn_regs.h"
34 #include "dwarf/h/dwarfExprParser.h"
35 #include "dwarf/h/dwarfResult.h"
36 #include "common/src/debug_common.h"
37 #include "common/h/VariableLocation.h"
38 #include "common/h/ProcReader.h"
39 #include "common/src/Types.h"
40
41 using namespace std;
42
43 namespace Dyninst {
44 namespace Dwarf {
45
46 bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
47                            long int *initialStackValue,
48                            VariableLocation &loc,
49                            Dyninst::Architecture arch) {
50    SymbolicDwarfResult res(loc, arch);
51    if (!decodeDwarfExpression(dwlocs, initialStackValue, 
52                               res, arch)) return false;
53    res.val();
54    return true;
55 }
56
57 bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
58                            long int *initialStackValue,
59                            ProcessReader *reader,
60                            Address pc,
61                            Dwarf_Debug dbg,
62                            Dyninst::Architecture arch,
63                            MachRegisterVal &end_result) {
64    ConcreteDwarfResult res(reader, arch, pc, dbg);
65    if (!decodeDwarfExpression(dwlocs, initialStackValue, 
66                               res, arch)) return false;
67    if (res.err()) return false;
68    end_result = res.val();
69    return true;
70 }
71
72
73
74 bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
75                            long int *initialStackValue,
76                            DwarfResult &cons,
77                            Dyninst::Architecture arch) {
78    // This is basically a decode passthrough, with the work
79    // being done by the DwarfResult. 
80
81    dwarf_printf("Entry to decodeDwarfExpression\n");
82
83    int addr_width = getArchAddressWidth(arch);
84    if (initialStackValue != NULL) {
85       dwarf_printf("\tInitializing expr stack with 0x%lx\n", initialStackValue);
86       cons.pushUnsignedVal((Dyninst::MachRegisterVal) *initialStackValue);
87    }
88
89    Dwarf_Loc *locations = dwlocs->ld_s;
90    unsigned count = dwlocs->ld_cents;
91    for ( unsigned int i = 0; i < count; i++ ) 
92    {
93       dwarf_printf("\tAtom %d of %d: val 0x%x\n", i, count, locations[i].lr_atom);
94       /* lit0 - lit31 : the constants 0..31 */
95       if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 ) 
96       {
97          dwarf_printf("\t\t Pushing unsigned val 0x%lx\n", locations[i].lr_atom - DW_OP_lit0);
98          cons.pushUnsignedVal((Dyninst::MachRegisterVal) (locations[i].lr_atom - DW_OP_lit0));
99          continue;
100       }
101
102       /* reg0 - reg31: named registers (not their constants) */
103       if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 ) 
104       {
105          dwarf_printf("\t\t Pushing reg %s\n",MachRegister::DwarfEncToReg(locations[i].lr_atom - DW_OP_reg0,
106                                                                           arch).name().c_str());
107
108          cons.pushReg(MachRegister::DwarfEncToReg(locations[i].lr_atom - DW_OP_reg0,
109                                                   arch));
110          continue;
111       }
112
113       /* breg0 - breg31: register contents plus an optional offset */
114       if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 ) 
115       {
116          dwarf_printf("\t\t Pushing reg %s + %d\n",MachRegister::DwarfEncToReg(locations[i].lr_atom - DW_OP_reg0,
117                                                                                arch).name().c_str(),
118                       locations[i].lr_number);
119          cons.readReg(MachRegister::DwarfEncToReg(locations[i].lr_atom - DW_OP_breg0,
120                                                   arch));
121          cons.pushSignedVal((Dyninst::MachRegisterVal) locations[i].lr_number);
122          cons.pushOp(DwarfResult::Add);
123          continue;
124       }
125
126       switch( locations[i].lr_atom ) {
127          // This is the same thing as breg, just with an encoded instead of literal
128          // register.
129          // The register is in lr_number
130          // The offset is in lr_number2
131          case DW_OP_bregx:
132             dwarf_printf("\t\t Pushing reg %s + %d\n",MachRegister::DwarfEncToReg(locations[i].lr_number,
133                                                                                   arch).name().c_str(),
134                          locations[i].lr_number2);
135             
136             cons.readReg(MachRegister::DwarfEncToReg(locations[i].lr_number, arch));
137             cons.pushSignedVal(locations[i].lr_number2);
138             cons.pushOp(DwarfResult::Add);
139             break;
140
141          case DW_OP_regx:
142             dwarf_printf("\t\t Pushing reg %s\n",MachRegister::DwarfEncToReg(locations[i].lr_number,
143                                                                                   arch).name().c_str());
144             cons.pushReg(MachRegister::DwarfEncToReg(locations[i].lr_number, arch));
145             break;
146             
147          case DW_OP_nop:
148             dwarf_printf("\t\t NOP\n");
149             break;
150
151          case DW_OP_addr:
152          case DW_OP_const1u:
153          case DW_OP_const2u:
154          case DW_OP_const4u:
155          case DW_OP_const8u:
156          case DW_OP_constu:
157             dwarf_printf("\t\t Pushing unsigned 0x%lx\n", locations[i].lr_number);
158             cons.pushUnsignedVal(locations[i].lr_number);
159             break;
160
161          case DW_OP_const1s:
162          case DW_OP_const2s:
163          case DW_OP_const4s:
164          case DW_OP_const8s:
165          case DW_OP_consts:
166             dwarf_printf("\t\t Pushing signed 0x%lx\n", locations[i].lr_number);
167             cons.pushSignedVal(locations[i].lr_number);
168             break;
169
170          case DW_OP_fbreg:
171             dwarf_printf("\t\t Pushing FB + 0x%lx\n", locations[i].lr_number);
172             cons.pushFrameBase();
173             cons.pushSignedVal(locations[i].lr_number);
174             cons.pushOp(DwarfResult::Add);
175             break;
176
177          case DW_OP_dup: 
178             dwarf_printf("\t\t Pushing dup\n");
179            cons.pushOp(DwarfResult::Pick, 0);
180             break;
181
182          case DW_OP_drop:
183             dwarf_printf("\t\t Pushing drop\n");
184             cons.pushOp(DwarfResult::Drop, 0);
185             break;
186
187          case DW_OP_pick: 
188             dwarf_printf("\t\t Pushing pick %d\n", locations[i].lr_number);
189             cons.pushOp(DwarfResult::Pick, locations[i].lr_number);
190             break;
191
192          case DW_OP_over: 
193             dwarf_printf("\t\t Pushing pick 1\n");
194             cons.pushOp(DwarfResult::Pick, 1);
195             break;
196
197          case DW_OP_swap: 
198             dwarf_printf("\t\t Pushing swap\n");
199             cons.pushOp(DwarfResult::Pick, 1);
200             cons.pushOp(DwarfResult::Drop, 2);
201             break;
202
203          case DW_OP_rot: 
204             dwarf_printf("\t\t Pushing rotate\n");
205             cons.pushOp(DwarfResult::Pick, 2);
206             cons.pushOp(DwarfResult::Pick, 2);
207             cons.pushOp(DwarfResult::Drop, 3);
208             cons.pushOp(DwarfResult::Drop, 3);
209             break;
210
211          case DW_OP_deref:
212             dwarf_printf("\t\t Pushing deref %d\n", addr_width);
213             cons.pushOp(DwarfResult::Deref, addr_width);
214             break;
215
216          case DW_OP_deref_size:
217             dwarf_printf("\t\t Pushing deref %d\n", locations[i].lr_number);
218             cons.pushOp(DwarfResult::Deref, locations[i].lr_number);
219             break;
220
221          case DW_OP_call_frame_cfa:
222             // This is a reference to the CFA as computed by stack walking information.
223             // The current order is:
224             // Variable: reference frame base (fbreg, above)
225             // Frame base: reference CFA
226             // CFA: offset from stack pointer
227             dwarf_printf("\t\t Pushing CFA\n");
228             cons.pushCFA();
229             break;
230
231          case DW_OP_abs:
232             dwarf_printf("\t\t Pushing abs\n");
233             cons.pushOp(DwarfResult::Abs);
234             break;
235
236          case DW_OP_and:
237             dwarf_printf("\t\t Pushing and\n");
238             cons.pushOp(DwarfResult::And);
239             break;
240
241          case DW_OP_div:
242             dwarf_printf("\t\t Pushing div\n");
243             cons.pushOp(DwarfResult::Div);
244             break;
245
246          case DW_OP_minus:
247             dwarf_printf("\t\t Pushing sub\n");
248             cons.pushOp(DwarfResult::Sub);
249             break;
250
251          case DW_OP_mod:
252             cons.pushOp(DwarfResult::Mod);
253             break;
254
255          case DW_OP_mul:
256             cons.pushOp(DwarfResult::Mul);
257             break;
258
259          case DW_OP_neg:
260             cons.pushSignedVal(-1);
261             cons.pushOp(DwarfResult::Mul);
262             break;
263
264          case DW_OP_not:
265             cons.pushOp(DwarfResult::Not);
266             break;
267
268          case DW_OP_or:
269             cons.pushOp(DwarfResult::Or);
270             break;
271
272          case DW_OP_plus:
273             dwarf_printf("\t\t Pushing add\n");
274             cons.pushOp(DwarfResult::Add);
275             break;
276
277          case DW_OP_plus_uconst:
278             dwarf_printf("\t\t Pushing add 0x%x\n", locations[i].lr_number);
279
280             cons.pushOp(DwarfResult::Add, locations[i].lr_number);
281             break;
282
283          case DW_OP_shl:
284             cons.pushOp(DwarfResult::Shl);
285             break;
286
287          case DW_OP_shr:
288             cons.pushOp(DwarfResult::Shr);
289             break;
290          
291          case DW_OP_shra:
292             cons.pushOp(DwarfResult::ShrArith);
293             break;
294
295          case DW_OP_xor:
296             cons.pushOp(DwarfResult::Xor);
297             break;
298
299          case DW_OP_le:
300             cons.pushOp(DwarfResult::LE);
301             break;
302
303          case DW_OP_ge:
304             cons.pushOp(DwarfResult::GE);
305             break;
306
307          case DW_OP_eq:
308             cons.pushOp(DwarfResult::Eq);
309             break;
310
311          case DW_OP_ne:
312             cons.pushOp(DwarfResult::Neq);
313             break;
314
315          case DW_OP_lt:
316             cons.pushOp(DwarfResult::LT);
317             break;
318
319          case DW_OP_gt:
320             cons.pushOp(DwarfResult::GT);
321             break;
322
323          case DW_OP_bra: {
324             // Conditional branch... 
325             // It needs immediate evaluation so we can continue processing
326             // the DWARF. 
327             Dyninst::MachRegisterVal value;
328
329             if (!cons.eval(value)) {
330                // Error in dwarf, or we're doing static. I'm not worrying about
331                // encoding a conditional branch in static eval right now. 
332                return false;
333             }
334             
335             if (value == 0) break;
336             // Do not break; fall through to skip
337          }
338          case DW_OP_skip: {
339             int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
340             unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
341             
342             int j = i;
343             if ( bytes < 0 ) {
344                for ( j = i - 1; j >= 0; j-- ) {
345                   if ( locations[j].lr_offset == target ) { break; }
346                } /* end search backward */
347             } else {
348                for ( j = i + 1; j < dwlocs->ld_cents; j ++ ) {
349                   if ( locations[j].lr_offset == target ) { break; }
350                } /* end search forward */
351             } /* end if positive offset */
352             
353             /* Because i will be incremented the next time around the loop. */
354             i = j - 1; 
355             break;
356          }
357       case DW_OP_piece:
358         // Should detect multiple of these...
359         continue;
360          default:
361             return false;
362       } /* end operand switch */
363    } /* end iteration over Dwarf_Loc entries. */
364
365    return true;
366 }
367
368 }
369
370 }
371
372 #if 0
373
374 #if defined(arch_x86_64)
375
376 #define IA32_MAX_MAP 7
377 #define AMD64_MAX_MAP 15
378 static int const amd64_register_map[] =
379   {
380     0,  // RAX
381     2,  // RDX
382     1,  // RCX
383     3,  // RBX
384     6,  // RSI
385     7,  // RDI
386     5,  // RBP
387     4,  // RSP
388     8, 9, 10, 11, 12, 13, 14, 15    // gp 8 - 15
389     /* This is incomplete. The x86_64 ABI specifies a mapping from
390        dwarf numbers (0-66) to ("architecture number"). Without a
391        corresponding mapping for the SVR4 dwarf-machine encoding for
392        IA-32, however, it is not meaningful to provide this mapping. */
393   };
394
395
396 int Dyninst::Register_DWARFtoMachineEnc32(int n)
397 {
398    return n;
399 }
400
401
402 int Dyninst::Register_DWARFtoMachineEnc64(int n)
403 {
404    if (n <= AMD64_MAX_MAP)
405       return amd64_register_map[n];
406    return n;
407 }
408
409 #endif
410
411 #endif
412
413
414
415 #if 0
416 bool Dyninst::decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
417                                     long int *initialStackValue,
418                                     VariableLocation *loc, bool &isLocSet,
419                                     ProcessReader *reader,
420                                     Dyninst::Architecture arch,
421                                     long int &end_result)
422 {
423    /* Initialize the stack. */
424    int addr_width = getArchAddressWidth(arch);
425    std::stack< long int > opStack = std::stack<long int>();
426    if ( initialStackValue != NULL ) { opStack.push( * initialStackValue ); }
427
428    Dwarf_Loc *locations = dwlocs->ld_s;
429    unsigned count = dwlocs->ld_cents;
430    for ( unsigned int i = 0; i < count; i++ ) 
431    {
432       /* Handle the literals w/o 32 case statements. */
433       if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 ) 
434       {
435          dwarf_printf( "pushing named constant: %d\n", locations[i].lr_atom - DW_OP_lit0 );
436          opStack.push( locations[i].lr_atom - DW_OP_lit0 );
437          continue;
438       }
439
440       /* Haandle registers w/o 32 case statements. */
441       if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 ) 
442       {
443          /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
444          dwarf_printf( "location is named register %d\n", 
445                        DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width) );
446          //loc->stClass = storageRegOffset;
447          if (loc) 
448          {
449             loc->stClass = storageReg;
450             loc->refClass = storageNoRef;
451             loc->frameOffset = 0;
452             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
453             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
454             //loc->frameOffset = 0;
455             isLocSet = true;
456          }
457          continue;
458       } 
459
460       /* Haandle registers w/o 32 case statements. */
461       if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 ) 
462       {
463          dwarf_printf( "setting storage class to named register, regNum to %d, offset %d\n", DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width), locations[i].lr_number );
464          long int to_push = 0;
465          if (loc) {
466             loc->stClass = storageRegOffset;
467             loc->refClass = storageNoRef;
468             loc->frameOffset = locations[i].lr_number ;
469             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
470             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
471             to_push = static_cast<long int>(locations[i].lr_number);
472          }
473          else if (reader) {
474             Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_atom - DW_OP_breg0,
475                                                     arch);
476             Dyninst::MachRegisterVal v;
477             bool result = reader->GetReg(r, v);
478             if (!result) {
479                return false;
480             }
481             to_push = (long int) v + locations[i].lr_number;
482          }
483             
484          opStack.push(to_push); 
485          continue;
486       }
487
488       switch( locations[i].lr_atom ) 
489       {
490          case DW_OP_addr:
491          case DW_OP_const1u:
492          case DW_OP_const2u:
493          case DW_OP_const4u:
494          case DW_OP_const8u:
495          case DW_OP_constu:
496             dwarf_printf( "pushing unsigned constant %lu\n", 
497                           (unsigned long)locations[i].lr_number );
498             opStack.push(static_cast<long int>(locations[i].lr_number));
499             break;
500
501          case DW_OP_const1s:
502          case DW_OP_const2s:
503          case DW_OP_const4s:
504          case DW_OP_const8s:
505          case DW_OP_consts:
506             dwarf_printf( "pushing signed constant %ld\n", 
507                           (signed long)(locations[i].lr_number) );
508             opStack.push(static_cast<long int>(locations[i].lr_number));
509             break;
510
511          case DW_OP_regx:
512             /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
513             dwarf_printf( "location is register %d\n", 
514                           DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width) );
515             if (loc) {
516                loc->stClass = storageReg;
517                loc->refClass = storageNoRef;
518                loc->reg = (int) DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width); 
519                loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_number, addr_width); 
520                loc->frameOffset = 0;
521                isLocSet = true;
522             }
523             break;
524
525          case DW_OP_fbreg:
526          {
527             dwarf_printf( "setting storage class to frame base\n" );
528             //if ( storageClass != NULL ) { * storageClass = storageFrameOffset; }
529             long int to_push = 0;
530             if (loc) {
531                loc->stClass = storageRegOffset;
532                loc->refClass = storageNoRef;
533                loc->frameOffset = 0;
534                loc->mr_reg = Dyninst::FrameBase;
535                to_push = static_cast<long int>(locations[i].lr_number);
536             }
537             else if (reader) {
538                Dyninst::MachRegister r = Dyninst::FrameBase;
539                Dyninst::MachRegisterVal v;
540                bool result = reader->GetReg(r, v);
541                if (!result) {
542                   return false;
543                }
544                to_push = (long int) v + locations[i].lr_number;               
545             }
546             opStack.push(to_push);
547          } break;          
548          case DW_OP_bregx: 
549          {
550             dwarf_printf( "setting storage class to register, regNum to %d\n", 
551                           locations[i].lr_number );
552             long int to_push = 0;
553             if (loc) {
554                loc->stClass = storageRegOffset;
555                loc->refClass = storageNoRef;
556                loc->reg = (int) DWARF_TO_MACHINE_ENC_W( locations[i].lr_number, addr_width );
557                loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W( locations[i].lr_number, addr_width );
558                loc->frameOffset = 0;
559                to_push = static_cast<long int>(locations[i].lr_number2);
560             }
561             else if (reader) {
562                Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_number, arch);
563                Dyninst::MachRegisterVal v;
564                bool result = reader->GetReg(r, v);
565                if (!result) {
566                   return false;
567                }
568                to_push = (long int) v + locations[i].lr_number2;
569             }
570             opStack.push(to_push);
571          } break;
572          case DW_OP_dup:
573             DWARF_FALSE_IF( opStack.size() < 1, 
574                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
575             opStack.push( opStack.top() );
576             break;
577
578          case DW_OP_drop:
579             DWARF_FALSE_IF( opStack.size() < 1, 
580                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
581             opStack.pop();
582             break;
583
584          case DW_OP_pick: 
585          {
586             /* Duplicate the entry at index locations[i].lr_number. */
587             std::stack< long int > temp = std::stack< long int >();
588             
589             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
590             {
591                temp.push( opStack.top() ); opStack.pop();
592             }
593             
594             long int dup = opStack.top();
595             
596             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
597             {
598                opStack.push( temp.top() ); temp.pop();
599             }
600             
601             opStack.push( dup );
602          } break;
603
604          case DW_OP_over: 
605          {
606             DWARF_FALSE_IF( opStack.size() < 2, 
607                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
608             long int first = opStack.top(); opStack.pop();
609             long int second = opStack.top(); opStack.pop();
610             opStack.push( second ); opStack.push( first ); opStack.push( second );
611          } break;
612          
613          case DW_OP_swap: 
614          {
615             DWARF_FALSE_IF( opStack.size() < 2, 
616                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
617             long int first = opStack.top(); opStack.pop();
618             long int second = opStack.top(); opStack.pop();
619             opStack.push( first ); opStack.push( second );
620          } break;
621          
622          case DW_OP_deref:
623          {
624             if (!reader)
625                break;
626             long int addr = opStack.top(); opStack.pop();
627             unsigned long to_push = 0;
628             bool bresult = false;
629             if (addr_width == 4) {
630                uint32_t v;
631                bresult = reader->ReadMem(addr, &v, sizeof(v));
632                to_push = (unsigned long) v;
633             }
634             else if (addr_width == 8) {
635                uint64_t v;
636                bresult = reader->ReadMem(addr, &v, sizeof(v));
637                to_push = (unsigned long) v;
638             }
639             DWARF_FALSE_IF(!bresult,
640                            "%s[%d]: Could not read from %lx\n", addr);
641             opStack.push(to_push);
642             break;
643          }
644          case DW_OP_deref_size:
645          {
646             if (!reader)
647                break;
648             long int addr = opStack.top(); opStack.pop();
649             int width = locations[i].lr_number;
650             unsigned long to_push = 0;
651             bool bresult = false;
652             if (width == 1) {
653                uint8_t v;
654                bresult = reader->ReadMem(addr, &v, sizeof(v));
655                to_push = (unsigned long) v;
656             }
657             if (width == 2) {
658                uint16_t v;
659                bresult = reader->ReadMem(addr, &v, sizeof(v));
660                to_push = (unsigned long) v;
661             }
662             if (width == 4) {
663                uint32_t v;
664                bresult = reader->ReadMem(addr, &v, sizeof(v));
665                to_push = (unsigned long) v;
666             }
667             else if (width == 8) {
668                uint64_t v;
669                bresult = reader->ReadMem(addr, &v, sizeof(v));
670                to_push = (long int) v;
671             }
672             DWARF_FALSE_IF(!bresult,
673                            "%s[%d]: Could not read from %lx\n", addr);
674             opStack.push(to_push);
675             break;
676          }
677
678          case DW_OP_rot: 
679          {
680             DWARF_FALSE_IF( opStack.size() < 3, 
681                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
682             long int first = opStack.top(); opStack.pop();
683             long int second = opStack.top(); opStack.pop();
684             long int third = opStack.top(); opStack.pop();
685             opStack.push( first ); opStack.push( third ); opStack.push( second );
686          } break;
687
688          case DW_OP_abs: 
689          {
690             DWARF_FALSE_IF( opStack.size() < 1, 
691                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
692             long int top = opStack.top(); opStack.pop();
693             opStack.push( abs( top ) );
694          } break;
695          
696          case DW_OP_and: 
697          {
698             DWARF_FALSE_IF( opStack.size() < 2, 
699                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
700             long int first = opStack.top(); opStack.pop();
701             long int second = opStack.top(); opStack.pop();
702             opStack.push( second & first );
703          } break;
704
705          case DW_OP_div: 
706          {
707             DWARF_FALSE_IF( opStack.size() < 2, 
708                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
709             long int first = opStack.top(); opStack.pop();
710             long int second = opStack.top(); opStack.pop();
711             DWARF_FALSE_IF(((second != 0) && (first == 0)),
712                            "%s[%d]: invalid stack, div operation with %d / %d, returning false\n",
713                            __FILE__, __LINE__, second, first);
714             
715             if((second == 0) && (first == 0)) 
716               opStack.push(0);
717             else
718               opStack.push( second / first );
719          } break;
720
721          case DW_OP_minus: 
722          {
723             DWARF_FALSE_IF( opStack.size() < 2, 
724                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
725             long int first = opStack.top(); opStack.pop();
726             long int second = opStack.top(); opStack.pop();
727             opStack.push( second - first );
728          } break;
729
730          case DW_OP_mod: 
731          {
732             DWARF_FALSE_IF( opStack.size() < 2, 
733                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
734             long int first = opStack.top(); opStack.pop();
735             long int second = opStack.top(); opStack.pop();
736             DWARF_FALSE_IF(((second != 0) && (first == 0)),
737                            "%s[%d]: invalid stack, mod operation with %d mod %d, returning false\n",
738                            __FILE__, __LINE__, second, first);
739             
740             if((second == 0) && (first == 0)) 
741               opStack.push(0);
742             else
743               opStack.push( second % first );
744          } break;
745
746          case DW_OP_mul: 
747          {
748             DWARF_FALSE_IF( opStack.size() < 2, 
749                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
750             long int first = opStack.top(); opStack.pop();
751             long int second = opStack.top(); opStack.pop();
752             opStack.push( second * first );
753          } break;
754
755          case DW_OP_neg: 
756          {
757             DWARF_FALSE_IF( opStack.size() < 1, 
758                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
759             long int first = opStack.top(); opStack.pop();
760             opStack.push( first * (-1) );
761          } break;
762          
763          case DW_OP_not: 
764          {
765             DWARF_FALSE_IF( opStack.size() < 1, 
766                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
767             long int first = opStack.top(); opStack.pop();
768             opStack.push( ~ first );
769          } break;
770
771          case DW_OP_or: 
772          {
773             DWARF_FALSE_IF( opStack.size() < 2, 
774                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
775             long int first = opStack.top(); opStack.pop();
776             long int second = opStack.top(); opStack.pop();
777             opStack.push( second | first );
778          } break;
779
780          case DW_OP_plus: 
781          {
782             DWARF_FALSE_IF( opStack.size() < 2, 
783                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
784             long int first = opStack.top(); opStack.pop();
785             long int second = opStack.top(); opStack.pop();
786             opStack.push( second + first );
787          } break;
788
789          case DW_OP_plus_uconst: 
790          {
791             DWARF_FALSE_IF( opStack.size() < 1, 
792                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
793             long int first = opStack.top(); opStack.pop();
794             opStack.push(static_cast<long int>(first + locations[i].lr_number));
795          } break;
796          
797          case DW_OP_shl: 
798          {
799             DWARF_FALSE_IF( opStack.size() < 2, 
800                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
801             long int first = opStack.top(); opStack.pop();
802             long int second = opStack.top(); opStack.pop();
803             opStack.push( second << first );
804          } break;
805
806          case DW_OP_shr: 
807          {
808             DWARF_FALSE_IF( opStack.size() < 2, 
809                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
810             long int first = opStack.top(); opStack.pop();
811             long int second = opStack.top(); opStack.pop();
812             
813             opStack.push( (long int)((unsigned long)second >> (unsigned long)first) );
814          } break;
815          
816          case DW_OP_shra: 
817          {
818             DWARF_FALSE_IF( opStack.size() < 2, 
819                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
820             long int first = opStack.top(); opStack.pop();
821             long int second = opStack.top(); opStack.pop();
822             opStack.push( second >> first );
823          } break;
824
825          case DW_OP_xor: 
826          {
827             DWARF_FALSE_IF( opStack.size() < 2, 
828                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
829             long int first = opStack.top(); opStack.pop();
830             long int second = opStack.top(); opStack.pop();
831             opStack.push( second ^ first );
832          } break;
833
834          case DW_OP_le: 
835          {
836             DWARF_FALSE_IF( opStack.size() < 2, 
837                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
838             long int first = opStack.top(); opStack.pop();
839             long int second = opStack.top(); opStack.pop();
840             opStack.push( first <= second ? 1 : 0 );
841          } break;
842
843          case DW_OP_ge: 
844          {
845             DWARF_FALSE_IF( opStack.size() < 2, 
846                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
847             long int first = opStack.top(); opStack.pop();
848             long int second = opStack.top(); opStack.pop();
849             opStack.push( first >= second ? 1 : 0 );
850          } break;
851
852          case DW_OP_eq: 
853          {
854             DWARF_FALSE_IF( opStack.size() < 2, 
855                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
856             long int first = opStack.top(); opStack.pop();
857             long int second = opStack.top(); opStack.pop();
858             opStack.push( first == second ? 1 : 0 );
859          } break;
860
861          case DW_OP_lt: 
862          {
863             DWARF_FALSE_IF( opStack.size() < 2, 
864                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
865             long int first = opStack.top(); opStack.pop();
866             long int second = opStack.top(); opStack.pop();
867             opStack.push( first < second ? 1 : 0 );
868          } break;
869
870          case DW_OP_gt: 
871          {
872             DWARF_FALSE_IF( opStack.size() < 2, 
873                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
874             long int first = opStack.top(); opStack.pop();
875             long int second = opStack.top(); opStack.pop();
876             opStack.push( first > second ? 1 : 0 );
877          } break;
878
879          case DW_OP_ne: 
880          {
881             DWARF_FALSE_IF( opStack.size() < 2, 
882                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
883             long int first = opStack.top(); opStack.pop();
884             long int second = opStack.top(); opStack.pop();
885             opStack.push( first != second ? 1 : 0 );
886          } break;
887
888          case DW_OP_bra:
889          {
890             DWARF_FALSE_IF( opStack.size() < 1, 
891                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
892             if ( opStack.top() == 0 ) { break; }
893             opStack.pop();
894          }
895          case DW_OP_skip: 
896          {
897             int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
898             unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
899             
900             int j = i;
901             if ( bytes < 0 ) {
902                for ( j = i - 1; j >= 0; j-- ) {
903                   if ( locations[j].lr_offset == target ) { break; }
904                } /* end search backward */
905             } else {
906                for ( j = i + 1; j < dwlocs->ld_cents; j ++ ) {
907                   if ( locations[j].lr_offset == target ) { break; }
908                } /* end search forward */
909             } /* end if positive offset */
910             
911             /* Because i will be incremented the next time around the loop. */
912             i = j - 1;
913          } break;
914
915          case DW_OP_piece:
916             /* For multi-part variables, which we don't handle. */
917             //bperr ( "Warning: dyninst does not handle multi-part variables.\n" );
918             break;
919
920          case DW_OP_nop:
921             break;
922
923          case DW_OP_call_frame_cfa: {
924             long int to_push = 0;
925             if (loc) {
926                loc->stClass = storageRegOffset;
927                loc->refClass = storageNoRef;
928                loc->frameOffset = 0;
929                loc->mr_reg = Dyninst::FrameBase;
930             }
931             else if (reader) {
932                Dyninst::MachRegister r = Dyninst::FrameBase;
933                Dyninst::MachRegisterVal v;
934                bool result = reader->GetReg(r, v);
935                if (!result) {
936                   return false;
937                }
938             }
939             opStack.push(to_push);
940             break;
941          }
942          default:
943             printf( "Unrecognized or non-static location opcode 0x%x, aborting.\n", locations[i].lr_atom );
944             return false;
945             break;
946       } /* end operand switch */
947    } /* end iteration over Dwarf_Loc entries. */
948    
949    if (opStack.empty()) {
950       dwarf_printf( "ignoring malformed location list (stack empty at end of list).\n" );
951       return isLocSet;
952    }
953    dwarf_printf( "Dwarf expression returning %d\n", opStack.top() );
954    end_result = opStack.top();
955    return true;
956 }
957
958 #endif
959