Fixes for accessing local variable via StackwalkerAPI
[dyninst.git] / common / h / dwarfExpr.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdint.h>
33 #include <stack>
34 #include "dynutil/h/dyn_regs.h"
35 #if !defined(DWARF_EXPR_H)
36 #define DWARF_EXPR_H
37
38 using namespace std;
39 using namespace Dyninst;
40
41 #if defined(arch_x86_64)
42 // We can only safely map the general purpose registers (0-7 on ia-32,
43 // 0-15 on amd-64)
44 #define IA32_MAX_MAP 7
45 #define AMD64_MAX_MAP 15
46 static int const amd64_register_map[] =
47   {
48     0,  // RAX
49     2,  // RDX
50     1,  // RCX
51     3,  // RBX
52     6,  // RSI
53     7,  // RDI
54     5,  // RBP
55     4,  // RSP
56     8, 9, 10, 11, 12, 13, 14, 15    // gp 8 - 15
57     /* This is incomplete. The x86_64 ABI specifies a mapping from
58        dwarf numbers (0-66) to ("architecture number"). Without a
59        corresponding mapping for the SVR4 dwarf-machine encoding for
60        IA-32, however, it is not meaningful to provide this mapping. */
61   };
62
63 int Register_DWARFtoMachineEnc32(int n)
64 {
65   if (n > IA32_MAX_MAP) {
66     dwarf_printf("%s[%d]: unexpected map lookup for DWARF register %d\n",
67                  __FILE__,__LINE__,n);
68   }
69   return n;
70 }
71
72
73 int Register_DWARFtoMachineEnc64(int n)
74 {
75   if (n <= AMD64_MAX_MAP)
76     return amd64_register_map[n];
77   else {
78     dwarf_printf("%s[%d]: unexpected map lookup for DWARF register %d\n",
79                  __FILE__,__LINE__,n);
80     return n;
81   }
82 }
83
84 #define DWARF_TO_MACHINE_ENC(n, proc)                                   \
85   ((proc->getAddressWidth() == 4) ? Register_DWARFtoMachineEnc32((int) n) : Register_DWARFtoMachineEnc64((int) n))
86 #define DWARF_TO_MACHINE_ENC_W(n, w) \
87   (w == 4) ? Register_DWARFtoMachineEnc32((int) n) : Register_DWARFtoMachineEnc64((int) n)
88 #define DWARF_TO_MACHINEREG_ENC_W(n, w) \
89    (w == 4) ? MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86) : MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86_64);
90 #else
91 #define DWARF_TO_MACHINE_ENC(n, proc) (n)
92 #define DWARF_TO_MACHINE_ENC_W(n, w) (n)
93 #define DWARF_TO_MACHINEREG_ENC_W(n, w) MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86);
94 #endif
95
96 #define DWARF_FALSE_IF(condition,...)           \
97   if ( condition ) { return false; }
98 #define DWARF_RETURN_IF(condition,...)          \
99   if ( condition ) { return; }
100 #define DWARF_NULL_IF(condition,...)            \
101   if ( condition ) { return NULL; }
102 #define DWARF_NEXT_IF(condition, ...)                                   \
103   if (condition) { if (depth != 1) { return false; } else {walk_error = true; break; } }
104
105
106 Dyninst::MachRegister DwarfToDynReg(Dwarf_Signed reg, Dyninst::Architecture arch)
107 {
108    return MachRegister::DwarfEncToReg(reg, arch);
109 }
110
111 Dwarf_Signed DynToDwarfReg(Dyninst::MachRegister reg)
112 {
113    return reg.getDwarfEnc();
114 }
115
116 bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
117                            long int *initialStackValue,
118                            VariableLocation *loc, bool &isLocSet,
119                            ProcessReader *reader,
120                            Dyninst::Architecture arch,
121                            long int &end_result)
122 {
123    /* Initialize the stack. */
124    int addr_width = getArchAddressWidth(arch);
125    std::stack< long int > opStack = std::stack<long int>();
126    if ( initialStackValue != NULL ) { opStack.push( * initialStackValue ); }
127
128    Dwarf_Loc *locations = dwlocs->ld_s;
129    unsigned count = dwlocs->ld_cents;
130    for ( unsigned int i = 0; i < count; i++ ) 
131    {
132       /* Handle the literals w/o 32 case statements. */
133       if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 ) 
134       {
135          dwarf_printf( "pushing named constant: %d\n", locations[i].lr_atom - DW_OP_lit0 );
136          opStack.push( locations[i].lr_atom - DW_OP_lit0 );
137          continue;
138       }
139
140       /* Haandle registers w/o 32 case statements. */
141       if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 ) 
142       {
143          /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
144          dwarf_printf( "location is named register %d\n", 
145                        DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width) );
146          //loc->stClass = storageRegOffset;
147          if (loc) 
148          {
149             loc->stClass = storageReg;
150             loc->refClass = storageNoRef;
151             loc->frameOffset = 0;
152             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
153             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
154             //loc->frameOffset = 0;
155             isLocSet = true;
156          }
157          continue;
158       } 
159
160       /* Haandle registers w/o 32 case statements. */
161       if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 ) 
162       {
163          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 );
164          long int to_push;
165          if (loc) {
166             loc->stClass = storageRegOffset;
167             loc->refClass = storageNoRef;
168             loc->frameOffset = locations[i].lr_number ;
169             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
170             loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
171             to_push = static_cast<long int>(locations[i].lr_number);
172          }
173          else if (reader) {
174             Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_atom - DW_OP_breg0,
175                                                     arch);
176             Dyninst::MachRegisterVal v;
177             bool result = reader->GetReg(r, v);
178             if (!result) {
179                return false;
180             }
181             to_push = (long int) v + locations[i].lr_number;
182          }
183             
184          opStack.push(to_push); 
185          continue;
186       }
187
188       switch( locations[i].lr_atom ) 
189       {
190          case DW_OP_addr:
191          case DW_OP_const1u:
192          case DW_OP_const2u:
193          case DW_OP_const4u:
194          case DW_OP_const8u:
195          case DW_OP_constu:
196             dwarf_printf( "pushing unsigned constant %lu\n", 
197                           (unsigned long)locations[i].lr_number );
198             opStack.push(static_cast<long int>(locations[i].lr_number));
199             break;
200
201          case DW_OP_const1s:
202          case DW_OP_const2s:
203          case DW_OP_const4s:
204          case DW_OP_const8s:
205          case DW_OP_consts:
206             dwarf_printf( "pushing signed constant %ld\n", 
207                           (signed long)(locations[i].lr_number) );
208             opStack.push(static_cast<long int>(locations[i].lr_number));
209             break;
210
211          case DW_OP_regx:
212             /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
213             dwarf_printf( "location is register %d\n", 
214                           DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width) );
215             if (loc) {
216                loc->stClass = storageReg;
217                loc->refClass = storageNoRef;
218                loc->reg = (int) DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width); 
219                loc->mr_reg = (int) DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_number, addr_width); 
220                loc->frameOffset = 0;
221                isLocSet = true;
222             }
223             break;
224
225          case DW_OP_fbreg:
226          {
227             dwarf_printf( "setting storage class to frame base\n" );
228             //if ( storageClass != NULL ) { * storageClass = storageFrameOffset; }
229             long int to_push = 0;
230             if (loc) {
231                loc->stClass = storageRegOffset;
232                loc->refClass = storageNoRef;
233                loc->frameOffset = 0;
234                to_push = static_cast<long int>(locations[i].lr_number);
235             }
236             else if (reader) {
237                Dyninst::MachRegister r = Dyninst::FrameBase;
238                Dyninst::MachRegisterVal v;
239                bool result = reader->GetReg(r, v);
240                if (!result) {
241                   return false;
242                }
243                to_push = (long int) v + locations[i].lr_number;               
244             }
245             opStack.push(to_push);
246          } break;          
247          case DW_OP_bregx: 
248          {
249             dwarf_printf( "setting storage class to register, regNum to %d\n", 
250                           locations[i].lr_number );
251             long int to_push = 0;
252             if (loc) {
253                loc->stClass = storageRegOffset;
254                loc->refClass = storageNoRef;
255                loc->reg = (int) DWARF_TO_MACHINE_ENC_W( locations[i].lr_number, addr_width );
256                loc->mr_reg = (int) DWARF_TO_MACHINEREG_ENC_W( locations[i].lr_number, addr_width );
257                loc->frameOffset = 0;
258                to_push = static_cast<long int>(locations[i].lr_number2);
259             }
260             else if (reader) {
261                Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_number, arch);
262                Dyninst::MachRegisterVal v;
263                bool result = reader->GetReg(r, v);
264                if (!result) {
265                   return false;
266                }
267                to_push = (long int) v + locations[i].lr_number2;
268             }
269             opStack.push(to_push);
270          } break;
271          case DW_OP_dup:
272             DWARF_FALSE_IF( opStack.size() < 1, 
273                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
274             opStack.push( opStack.top() );
275             break;
276
277          case DW_OP_drop:
278             DWARF_FALSE_IF( opStack.size() < 1, 
279                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
280             opStack.pop();
281             break;
282
283          case DW_OP_pick: 
284          {
285             /* Duplicate the entry at index locations[i].lr_number. */
286             std::stack< long int > temp = std::stack< long int >();
287             
288             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
289             {
290                temp.push( opStack.top() ); opStack.pop();
291             }
292             
293             long int dup = opStack.top();
294             
295             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
296             {
297                opStack.push( temp.top() ); temp.pop();
298             }
299             
300             opStack.push( dup );
301          } break;
302
303          case DW_OP_over: 
304          {
305             DWARF_FALSE_IF( opStack.size() < 2, 
306                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
307             long int first = opStack.top(); opStack.pop();
308             long int second = opStack.top(); opStack.pop();
309             opStack.push( second ); opStack.push( first ); opStack.push( second );
310          } break;
311          
312          case DW_OP_swap: 
313          {
314             DWARF_FALSE_IF( opStack.size() < 2, 
315                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
316             long int first = opStack.top(); opStack.pop();
317             long int second = opStack.top(); opStack.pop();
318             opStack.push( first ); opStack.push( second );
319          } break;
320          
321          case DW_OP_deref:
322          {
323             if (!reader)
324                break;
325             long int addr = opStack.top(); opStack.pop();
326             unsigned long to_push = 0;
327             bool bresult = false;
328             if (addr_width == 4) {
329                uint32_t v;
330                bresult = reader->ReadMem(addr, &v, sizeof(v));
331                to_push = (unsigned long) v;
332             }
333             else if (addr_width == 8) {
334                uint64_t v;
335                bresult = reader->ReadMem(addr, &v, sizeof(v));
336                to_push = (unsigned long) v;
337             }
338             DWARF_FALSE_IF(!bresult,
339                            "%s[%d]: Could not read from %lx\n", addr);
340             opStack.push(to_push);
341             break;
342          }
343          case DW_OP_deref_size:
344          {
345             if (!reader)
346                break;
347             long int addr = opStack.top(); opStack.pop();
348             int width = locations[i].lr_number;
349             unsigned long to_push = 0;
350             bool bresult = false;
351             if (width == 1) {
352                uint8_t v;
353                bresult = reader->ReadMem(addr, &v, sizeof(v));
354                to_push = (unsigned long) v;
355             }
356             if (width == 2) {
357                uint16_t v;
358                bresult = reader->ReadMem(addr, &v, sizeof(v));
359                to_push = (unsigned long) v;
360             }
361             if (width == 4) {
362                uint32_t v;
363                bresult = reader->ReadMem(addr, &v, sizeof(v));
364                to_push = (unsigned long) v;
365             }
366             else if (width == 8) {
367                uint64_t v;
368                bresult = reader->ReadMem(addr, &v, sizeof(v));
369                to_push = (long int) v;
370             }
371             DWARF_FALSE_IF(!bresult,
372                            "%s[%d]: Could not read from %lx\n", addr);
373             opStack.push(to_push);
374             break;
375          }
376          case DW_OP_rot: 
377          {
378             DWARF_FALSE_IF( opStack.size() < 3, 
379                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
380             long int first = opStack.top(); opStack.pop();
381             long int second = opStack.top(); opStack.pop();
382             long int third = opStack.top(); opStack.pop();
383             opStack.push( first ); opStack.push( third ); opStack.push( second );
384          } break;
385
386          case DW_OP_abs: 
387          {
388             DWARF_FALSE_IF( opStack.size() < 1, 
389                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
390             long int top = opStack.top(); opStack.pop();
391             opStack.push( abs( top ) );
392          } break;
393          
394          case DW_OP_and: 
395          {
396             DWARF_FALSE_IF( opStack.size() < 2, 
397                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
398             long int first = opStack.top(); opStack.pop();
399             long int second = opStack.top(); opStack.pop();
400             opStack.push( second & first );
401          } break;
402
403          case DW_OP_div: 
404          {
405             DWARF_FALSE_IF( opStack.size() < 2, 
406                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
407             long int first = opStack.top(); opStack.pop();
408             long int second = opStack.top(); opStack.pop();
409             opStack.push( second / first );
410          } break;
411
412          case DW_OP_minus: 
413          {
414             DWARF_FALSE_IF( opStack.size() < 2, 
415                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
416             long int first = opStack.top(); opStack.pop();
417             long int second = opStack.top(); opStack.pop();
418             opStack.push( second - first );
419          } break;
420
421          case DW_OP_mod: 
422          {
423             DWARF_FALSE_IF( opStack.size() < 2, 
424                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
425             long int first = opStack.top(); opStack.pop();
426             long int second = opStack.top(); opStack.pop();
427             opStack.push( second % first );
428          } break;
429
430          case DW_OP_mul: 
431          {
432             DWARF_FALSE_IF( opStack.size() < 2, 
433                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
434             long int first = opStack.top(); opStack.pop();
435             long int second = opStack.top(); opStack.pop();
436             opStack.push( second * first );
437          } break;
438
439          case DW_OP_neg: 
440          {
441             DWARF_FALSE_IF( opStack.size() < 1, 
442                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
443             long int first = opStack.top(); opStack.pop();
444             opStack.push( first * (-1) );
445          } break;
446          
447          case DW_OP_not: 
448          {
449             DWARF_FALSE_IF( opStack.size() < 1, 
450                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
451             long int first = opStack.top(); opStack.pop();
452             opStack.push( ~ first );
453          } break;
454
455          case DW_OP_or: 
456          {
457             DWARF_FALSE_IF( opStack.size() < 2, 
458                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
459             long int first = opStack.top(); opStack.pop();
460             long int second = opStack.top(); opStack.pop();
461             opStack.push( second | first );
462          } break;
463
464          case DW_OP_plus: 
465          {
466             DWARF_FALSE_IF( opStack.size() < 2, 
467                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
468             long int first = opStack.top(); opStack.pop();
469             long int second = opStack.top(); opStack.pop();
470             opStack.push( second + first );
471          } break;
472
473          case DW_OP_plus_uconst: 
474          {
475             DWARF_FALSE_IF( opStack.size() < 1, 
476                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
477             long int first = opStack.top(); opStack.pop();
478             opStack.push(static_cast<long int>(first + locations[i].lr_number));
479          } break;
480          
481          case DW_OP_shl: 
482          {
483             DWARF_FALSE_IF( opStack.size() < 2, 
484                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
485             long int first = opStack.top(); opStack.pop();
486             long int second = opStack.top(); opStack.pop();
487             opStack.push( second << first );
488          } break;
489
490          case DW_OP_shr: 
491          {
492             DWARF_FALSE_IF( opStack.size() < 2, 
493                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
494             long int first = opStack.top(); opStack.pop();
495             long int second = opStack.top(); opStack.pop();
496             
497             opStack.push( (long int)((unsigned long)second >> (unsigned long)first) );
498          } break;
499          
500          case DW_OP_shra: 
501          {
502             DWARF_FALSE_IF( opStack.size() < 2, 
503                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
504             long int first = opStack.top(); opStack.pop();
505             long int second = opStack.top(); opStack.pop();
506             opStack.push( second >> first );
507          } break;
508
509          case DW_OP_xor: 
510          {
511             DWARF_FALSE_IF( opStack.size() < 2, 
512                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
513             long int first = opStack.top(); opStack.pop();
514             long int second = opStack.top(); opStack.pop();
515             opStack.push( second ^ first );
516          } break;
517
518          case DW_OP_le: 
519          {
520             DWARF_FALSE_IF( opStack.size() < 2, 
521                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
522             long int first = opStack.top(); opStack.pop();
523             long int second = opStack.top(); opStack.pop();
524             opStack.push( first <= second ? 1 : 0 );
525          } break;
526
527          case DW_OP_ge: 
528          {
529             DWARF_FALSE_IF( opStack.size() < 2, 
530                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
531             long int first = opStack.top(); opStack.pop();
532             long int second = opStack.top(); opStack.pop();
533             opStack.push( first >= second ? 1 : 0 );
534          } break;
535
536          case DW_OP_eq: 
537          {
538             DWARF_FALSE_IF( opStack.size() < 2, 
539                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
540             long int first = opStack.top(); opStack.pop();
541             long int second = opStack.top(); opStack.pop();
542             opStack.push( first == second ? 1 : 0 );
543          } break;
544
545          case DW_OP_lt: 
546          {
547             DWARF_FALSE_IF( opStack.size() < 2, 
548                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
549             long int first = opStack.top(); opStack.pop();
550             long int second = opStack.top(); opStack.pop();
551             opStack.push( first < second ? 1 : 0 );
552          } break;
553
554          case DW_OP_gt: 
555          {
556             DWARF_FALSE_IF( opStack.size() < 2, 
557                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
558             long int first = opStack.top(); opStack.pop();
559             long int second = opStack.top(); opStack.pop();
560             opStack.push( first > second ? 1 : 0 );
561          } break;
562
563          case DW_OP_ne: 
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( first != second ? 1 : 0 );
570          } break;
571
572          case DW_OP_bra:
573          {
574             DWARF_FALSE_IF( opStack.size() < 1, 
575                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
576             if ( opStack.top() == 0 ) { break; }
577             opStack.pop();
578          }
579          case DW_OP_skip: 
580          {
581             int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
582             unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
583             
584             int j = i;
585             if ( bytes < 0 ) {
586                for ( j = i - 1; j >= 0; j-- ) {
587                   if ( locations[j].lr_offset == target ) { break; }
588                } /* end search backward */
589             } else {
590                for ( j = i + 1; j < dwlocs->ld_cents; j ++ ) {
591                   if ( locations[j].lr_offset == target ) { break; }
592                } /* end search forward */
593             } /* end if positive offset */
594             
595             /* Because i will be incremented the next time around the loop. */
596             i = j - 1;
597          } break;
598
599          case DW_OP_piece:
600             /* For multi-part variables, which we don't handle. */
601             //bperr ( "Warning: dyninst does not handle multi-part variables.\n" );
602             break;
603
604          case DW_OP_nop:
605             break;
606
607          default:
608             dwarf_printf( "Unrecognized or non-static location opcode 0x%x, aborting.\n", locations[i].lr_atom );
609             return false;
610             break;
611       } /* end operand switch */
612    } /* end iteration over Dwarf_Loc entries. */
613    
614    if (opStack.empty()) {
615       dwarf_printf( "ignoring malformed location list (stack empty at end of list).\n" );
616       return isLocSet;
617    }
618    dwarf_printf( "Dwarf expression returning %d\n", opStack.top() );
619    end_result = opStack.top();
620    return true;
621 }
622
623 #endif