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