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