Move dynutil/h to common/h; move common/h to common/src. Update CMakeLists.txt
[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             
358          default:
359             return false;
360       } /* end operand switch */
361    } /* end iteration over Dwarf_Loc entries. */
362
363    return true;
364 }
365
366 }
367
368 }
369
370 #if 0
371
372 #if defined(arch_x86_64)
373
374 #define IA32_MAX_MAP 7
375 #define AMD64_MAX_MAP 15
376 static int const amd64_register_map[] =
377   {
378     0,  // RAX
379     2,  // RDX
380     1,  // RCX
381     3,  // RBX
382     6,  // RSI
383     7,  // RDI
384     5,  // RBP
385     4,  // RSP
386     8, 9, 10, 11, 12, 13, 14, 15    // gp 8 - 15
387     /* This is incomplete. The x86_64 ABI specifies a mapping from
388        dwarf numbers (0-66) to ("architecture number"). Without a
389        corresponding mapping for the SVR4 dwarf-machine encoding for
390        IA-32, however, it is not meaningful to provide this mapping. */
391   };
392
393
394 int Dyninst::Register_DWARFtoMachineEnc32(int n)
395 {
396    return n;
397 }
398
399
400 int Dyninst::Register_DWARFtoMachineEnc64(int n)
401 {
402    if (n <= AMD64_MAX_MAP)
403       return amd64_register_map[n];
404    return n;
405 }
406
407 #endif
408
409 #endif
410
411
412
413 #if 0
414 bool Dyninst::decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
415                                     long int *initialStackValue,
416                                     VariableLocation *loc, bool &isLocSet,
417                                     ProcessReader *reader,
418                                     Dyninst::Architecture arch,
419                                     long int &end_result)
420 {
421    /* Initialize the stack. */
422    int addr_width = getArchAddressWidth(arch);
423    std::stack< long int > opStack = std::stack<long int>();
424    if ( initialStackValue != NULL ) { opStack.push( * initialStackValue ); }
425
426    Dwarf_Loc *locations = dwlocs->ld_s;
427    unsigned count = dwlocs->ld_cents;
428    for ( unsigned int i = 0; i < count; i++ ) 
429    {
430       /* Handle the literals w/o 32 case statements. */
431       if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 ) 
432       {
433          dwarf_printf( "pushing named constant: %d\n", locations[i].lr_atom - DW_OP_lit0 );
434          opStack.push( locations[i].lr_atom - DW_OP_lit0 );
435          continue;
436       }
437
438       /* Haandle registers w/o 32 case statements. */
439       if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 ) 
440       {
441          /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
442          dwarf_printf( "location is named register %d\n", 
443                        DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width) );
444          //loc->stClass = storageRegOffset;
445          if (loc) 
446          {
447             loc->stClass = storageReg;
448             loc->refClass = storageNoRef;
449             loc->frameOffset = 0;
450             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
451             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
452             //loc->frameOffset = 0;
453             isLocSet = true;
454          }
455          continue;
456       } 
457
458       /* Haandle registers w/o 32 case statements. */
459       if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 ) 
460       {
461          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 );
462          long int to_push = 0;
463          if (loc) {
464             loc->stClass = storageRegOffset;
465             loc->refClass = storageNoRef;
466             loc->frameOffset = locations[i].lr_number ;
467             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
468             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
469             to_push = static_cast<long int>(locations[i].lr_number);
470          }
471          else if (reader) {
472             Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_atom - DW_OP_breg0,
473                                                     arch);
474             Dyninst::MachRegisterVal v;
475             bool result = reader->GetReg(r, v);
476             if (!result) {
477                return false;
478             }
479             to_push = (long int) v + locations[i].lr_number;
480          }
481             
482          opStack.push(to_push); 
483          continue;
484       }
485
486       switch( locations[i].lr_atom ) 
487       {
488          case DW_OP_addr:
489          case DW_OP_const1u:
490          case DW_OP_const2u:
491          case DW_OP_const4u:
492          case DW_OP_const8u:
493          case DW_OP_constu:
494             dwarf_printf( "pushing unsigned constant %lu\n", 
495                           (unsigned long)locations[i].lr_number );
496             opStack.push(static_cast<long int>(locations[i].lr_number));
497             break;
498
499          case DW_OP_const1s:
500          case DW_OP_const2s:
501          case DW_OP_const4s:
502          case DW_OP_const8s:
503          case DW_OP_consts:
504             dwarf_printf( "pushing signed constant %ld\n", 
505                           (signed long)(locations[i].lr_number) );
506             opStack.push(static_cast<long int>(locations[i].lr_number));
507             break;
508
509          case DW_OP_regx:
510             /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
511             dwarf_printf( "location is register %d\n", 
512                           DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width) );
513             if (loc) {
514                loc->stClass = storageReg;
515                loc->refClass = storageNoRef;
516                loc->reg = (int) DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width); 
517                loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_number, addr_width); 
518                loc->frameOffset = 0;
519                isLocSet = true;
520             }
521             break;
522
523          case DW_OP_fbreg:
524          {
525             dwarf_printf( "setting storage class to frame base\n" );
526             //if ( storageClass != NULL ) { * storageClass = storageFrameOffset; }
527             long int to_push = 0;
528             if (loc) {
529                loc->stClass = storageRegOffset;
530                loc->refClass = storageNoRef;
531                loc->frameOffset = 0;
532                loc->mr_reg = Dyninst::FrameBase;
533                to_push = static_cast<long int>(locations[i].lr_number);
534             }
535             else if (reader) {
536                Dyninst::MachRegister r = Dyninst::FrameBase;
537                Dyninst::MachRegisterVal v;
538                bool result = reader->GetReg(r, v);
539                if (!result) {
540                   return false;
541                }
542                to_push = (long int) v + locations[i].lr_number;               
543             }
544             opStack.push(to_push);
545          } break;          
546          case DW_OP_bregx: 
547          {
548             dwarf_printf( "setting storage class to register, regNum to %d\n", 
549                           locations[i].lr_number );
550             long int to_push = 0;
551             if (loc) {
552                loc->stClass = storageRegOffset;
553                loc->refClass = storageNoRef;
554                loc->reg = (int) DWARF_TO_MACHINE_ENC_W( locations[i].lr_number, addr_width );
555                loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W( locations[i].lr_number, addr_width );
556                loc->frameOffset = 0;
557                to_push = static_cast<long int>(locations[i].lr_number2);
558             }
559             else if (reader) {
560                Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_number, arch);
561                Dyninst::MachRegisterVal v;
562                bool result = reader->GetReg(r, v);
563                if (!result) {
564                   return false;
565                }
566                to_push = (long int) v + locations[i].lr_number2;
567             }
568             opStack.push(to_push);
569          } break;
570          case DW_OP_dup:
571             DWARF_FALSE_IF( opStack.size() < 1, 
572                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
573             opStack.push( opStack.top() );
574             break;
575
576          case DW_OP_drop:
577             DWARF_FALSE_IF( opStack.size() < 1, 
578                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
579             opStack.pop();
580             break;
581
582          case DW_OP_pick: 
583          {
584             /* Duplicate the entry at index locations[i].lr_number. */
585             std::stack< long int > temp = std::stack< long int >();
586             
587             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
588             {
589                temp.push( opStack.top() ); opStack.pop();
590             }
591             
592             long int dup = opStack.top();
593             
594             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
595             {
596                opStack.push( temp.top() ); temp.pop();
597             }
598             
599             opStack.push( dup );
600          } break;
601
602          case DW_OP_over: 
603          {
604             DWARF_FALSE_IF( opStack.size() < 2, 
605                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
606             long int first = opStack.top(); opStack.pop();
607             long int second = opStack.top(); opStack.pop();
608             opStack.push( second ); opStack.push( first ); opStack.push( second );
609          } break;
610          
611          case DW_OP_swap: 
612          {
613             DWARF_FALSE_IF( opStack.size() < 2, 
614                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
615             long int first = opStack.top(); opStack.pop();
616             long int second = opStack.top(); opStack.pop();
617             opStack.push( first ); opStack.push( second );
618          } break;
619          
620          case DW_OP_deref:
621          {
622             if (!reader)
623                break;
624             long int addr = opStack.top(); opStack.pop();
625             unsigned long to_push = 0;
626             bool bresult = false;
627             if (addr_width == 4) {
628                uint32_t v;
629                bresult = reader->ReadMem(addr, &v, sizeof(v));
630                to_push = (unsigned long) v;
631             }
632             else if (addr_width == 8) {
633                uint64_t v;
634                bresult = reader->ReadMem(addr, &v, sizeof(v));
635                to_push = (unsigned long) v;
636             }
637             DWARF_FALSE_IF(!bresult,
638                            "%s[%d]: Could not read from %lx\n", addr);
639             opStack.push(to_push);
640             break;
641          }
642          case DW_OP_deref_size:
643          {
644             if (!reader)
645                break;
646             long int addr = opStack.top(); opStack.pop();
647             int width = locations[i].lr_number;
648             unsigned long to_push = 0;
649             bool bresult = false;
650             if (width == 1) {
651                uint8_t v;
652                bresult = reader->ReadMem(addr, &v, sizeof(v));
653                to_push = (unsigned long) v;
654             }
655             if (width == 2) {
656                uint16_t v;
657                bresult = reader->ReadMem(addr, &v, sizeof(v));
658                to_push = (unsigned long) v;
659             }
660             if (width == 4) {
661                uint32_t v;
662                bresult = reader->ReadMem(addr, &v, sizeof(v));
663                to_push = (unsigned long) v;
664             }
665             else if (width == 8) {
666                uint64_t v;
667                bresult = reader->ReadMem(addr, &v, sizeof(v));
668                to_push = (long int) v;
669             }
670             DWARF_FALSE_IF(!bresult,
671                            "%s[%d]: Could not read from %lx\n", addr);
672             opStack.push(to_push);
673             break;
674          }
675
676          case DW_OP_rot: 
677          {
678             DWARF_FALSE_IF( opStack.size() < 3, 
679                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
680             long int first = opStack.top(); opStack.pop();
681             long int second = opStack.top(); opStack.pop();
682             long int third = opStack.top(); opStack.pop();
683             opStack.push( first ); opStack.push( third ); opStack.push( second );
684          } break;
685
686          case DW_OP_abs: 
687          {
688             DWARF_FALSE_IF( opStack.size() < 1, 
689                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
690             long int top = opStack.top(); opStack.pop();
691             opStack.push( abs( top ) );
692          } break;
693          
694          case DW_OP_and: 
695          {
696             DWARF_FALSE_IF( opStack.size() < 2, 
697                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
698             long int first = opStack.top(); opStack.pop();
699             long int second = opStack.top(); opStack.pop();
700             opStack.push( second & first );
701          } break;
702
703          case DW_OP_div: 
704          {
705             DWARF_FALSE_IF( opStack.size() < 2, 
706                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
707             long int first = opStack.top(); opStack.pop();
708             long int second = opStack.top(); opStack.pop();
709             DWARF_FALSE_IF(((second != 0) && (first == 0)),
710                            "%s[%d]: invalid stack, div operation with %d / %d, returning false\n",
711                            __FILE__, __LINE__, second, first);
712             
713             if((second == 0) && (first == 0)) 
714               opStack.push(0);
715             else
716               opStack.push( second / first );
717          } break;
718
719          case DW_OP_minus: 
720          {
721             DWARF_FALSE_IF( opStack.size() < 2, 
722                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
723             long int first = opStack.top(); opStack.pop();
724             long int second = opStack.top(); opStack.pop();
725             opStack.push( second - first );
726          } break;
727
728          case DW_OP_mod: 
729          {
730             DWARF_FALSE_IF( opStack.size() < 2, 
731                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
732             long int first = opStack.top(); opStack.pop();
733             long int second = opStack.top(); opStack.pop();
734             DWARF_FALSE_IF(((second != 0) && (first == 0)),
735                            "%s[%d]: invalid stack, mod operation with %d mod %d, returning false\n",
736                            __FILE__, __LINE__, second, first);
737             
738             if((second == 0) && (first == 0)) 
739               opStack.push(0);
740             else
741               opStack.push( second % first );
742          } break;
743
744          case DW_OP_mul: 
745          {
746             DWARF_FALSE_IF( opStack.size() < 2, 
747                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
748             long int first = opStack.top(); opStack.pop();
749             long int second = opStack.top(); opStack.pop();
750             opStack.push( second * first );
751          } break;
752
753          case DW_OP_neg: 
754          {
755             DWARF_FALSE_IF( opStack.size() < 1, 
756                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
757             long int first = opStack.top(); opStack.pop();
758             opStack.push( first * (-1) );
759          } break;
760          
761          case DW_OP_not: 
762          {
763             DWARF_FALSE_IF( opStack.size() < 1, 
764                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
765             long int first = opStack.top(); opStack.pop();
766             opStack.push( ~ first );
767          } break;
768
769          case DW_OP_or: 
770          {
771             DWARF_FALSE_IF( opStack.size() < 2, 
772                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
773             long int first = opStack.top(); opStack.pop();
774             long int second = opStack.top(); opStack.pop();
775             opStack.push( second | first );
776          } break;
777
778          case DW_OP_plus: 
779          {
780             DWARF_FALSE_IF( opStack.size() < 2, 
781                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
782             long int first = opStack.top(); opStack.pop();
783             long int second = opStack.top(); opStack.pop();
784             opStack.push( second + first );
785          } break;
786
787          case DW_OP_plus_uconst: 
788          {
789             DWARF_FALSE_IF( opStack.size() < 1, 
790                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
791             long int first = opStack.top(); opStack.pop();
792             opStack.push(static_cast<long int>(first + locations[i].lr_number));
793          } break;
794          
795          case DW_OP_shl: 
796          {
797             DWARF_FALSE_IF( opStack.size() < 2, 
798                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
799             long int first = opStack.top(); opStack.pop();
800             long int second = opStack.top(); opStack.pop();
801             opStack.push( second << first );
802          } break;
803
804          case DW_OP_shr: 
805          {
806             DWARF_FALSE_IF( opStack.size() < 2, 
807                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
808             long int first = opStack.top(); opStack.pop();
809             long int second = opStack.top(); opStack.pop();
810             
811             opStack.push( (long int)((unsigned long)second >> (unsigned long)first) );
812          } break;
813          
814          case DW_OP_shra: 
815          {
816             DWARF_FALSE_IF( opStack.size() < 2, 
817                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
818             long int first = opStack.top(); opStack.pop();
819             long int second = opStack.top(); opStack.pop();
820             opStack.push( second >> first );
821          } break;
822
823          case DW_OP_xor: 
824          {
825             DWARF_FALSE_IF( opStack.size() < 2, 
826                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
827             long int first = opStack.top(); opStack.pop();
828             long int second = opStack.top(); opStack.pop();
829             opStack.push( second ^ first );
830          } break;
831
832          case DW_OP_le: 
833          {
834             DWARF_FALSE_IF( opStack.size() < 2, 
835                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
836             long int first = opStack.top(); opStack.pop();
837             long int second = opStack.top(); opStack.pop();
838             opStack.push( first <= second ? 1 : 0 );
839          } break;
840
841          case DW_OP_ge: 
842          {
843             DWARF_FALSE_IF( opStack.size() < 2, 
844                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
845             long int first = opStack.top(); opStack.pop();
846             long int second = opStack.top(); opStack.pop();
847             opStack.push( first >= second ? 1 : 0 );
848          } break;
849
850          case DW_OP_eq: 
851          {
852             DWARF_FALSE_IF( opStack.size() < 2, 
853                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
854             long int first = opStack.top(); opStack.pop();
855             long int second = opStack.top(); opStack.pop();
856             opStack.push( first == second ? 1 : 0 );
857          } break;
858
859          case DW_OP_lt: 
860          {
861             DWARF_FALSE_IF( opStack.size() < 2, 
862                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
863             long int first = opStack.top(); opStack.pop();
864             long int second = opStack.top(); opStack.pop();
865             opStack.push( first < second ? 1 : 0 );
866          } break;
867
868          case DW_OP_gt: 
869          {
870             DWARF_FALSE_IF( opStack.size() < 2, 
871                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
872             long int first = opStack.top(); opStack.pop();
873             long int second = opStack.top(); opStack.pop();
874             opStack.push( first > second ? 1 : 0 );
875          } break;
876
877          case DW_OP_ne: 
878          {
879             DWARF_FALSE_IF( opStack.size() < 2, 
880                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
881             long int first = opStack.top(); opStack.pop();
882             long int second = opStack.top(); opStack.pop();
883             opStack.push( first != second ? 1 : 0 );
884          } break;
885
886          case DW_OP_bra:
887          {
888             DWARF_FALSE_IF( opStack.size() < 1, 
889                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
890             if ( opStack.top() == 0 ) { break; }
891             opStack.pop();
892          }
893          case DW_OP_skip: 
894          {
895             int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
896             unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
897             
898             int j = i;
899             if ( bytes < 0 ) {
900                for ( j = i - 1; j >= 0; j-- ) {
901                   if ( locations[j].lr_offset == target ) { break; }
902                } /* end search backward */
903             } else {
904                for ( j = i + 1; j < dwlocs->ld_cents; j ++ ) {
905                   if ( locations[j].lr_offset == target ) { break; }
906                } /* end search forward */
907             } /* end if positive offset */
908             
909             /* Because i will be incremented the next time around the loop. */
910             i = j - 1;
911          } break;
912
913          case DW_OP_piece:
914             /* For multi-part variables, which we don't handle. */
915             //bperr ( "Warning: dyninst does not handle multi-part variables.\n" );
916             break;
917
918          case DW_OP_nop:
919             break;
920
921          case DW_OP_call_frame_cfa: {
922             long int to_push = 0;
923             if (loc) {
924                loc->stClass = storageRegOffset;
925                loc->refClass = storageNoRef;
926                loc->frameOffset = 0;
927                loc->mr_reg = Dyninst::FrameBase;
928             }
929             else if (reader) {
930                Dyninst::MachRegister r = Dyninst::FrameBase;
931                Dyninst::MachRegisterVal v;
932                bool result = reader->GetReg(r, v);
933                if (!result) {
934                   return false;
935                }
936             }
937             opStack.push(to_push);
938             break;
939          }
940          default:
941             printf( "Unrecognized or non-static location opcode 0x%x, aborting.\n", locations[i].lr_atom );
942             return false;
943             break;
944       } /* end operand switch */
945    } /* end iteration over Dwarf_Loc entries. */
946    
947    if (opStack.empty()) {
948       dwarf_printf( "ignoring malformed location list (stack empty at end of list).\n" );
949       return isLocSet;
950    }
951    dwarf_printf( "Dwarf expression returning %d\n", opStack.top() );
952    end_result = opStack.top();
953    return true;
954 }
955
956 #endif
957