Added missing header files
[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 #else
89 #define DWARF_TO_MACHINE_ENC(n, proc) (n)
90 #define DWARF_TO_MACHINE_ENC_W(n, w) (n)
91 #endif
92
93 #define DWARF_FALSE_IF(condition,...)           \
94   if ( condition ) { return false; }
95 #define DWARF_RETURN_IF(condition,...)          \
96   if ( condition ) { return; }
97 #define DWARF_NULL_IF(condition,...)            \
98   if ( condition ) { return NULL; }
99 #define DWARF_NEXT_IF(condition, ...)                                   \
100   if (condition) { if (depth != 1) { return false; } else {walk_error = true; break; } }
101
102
103 Dyninst::MachRegister DwarfToDynReg(Dwarf_Signed reg, Dyninst::Architecture arch)
104 {
105    return MachRegister::DwarfEncToReg(reg, arch);
106 }
107
108 Dwarf_Signed DynToDwarfReg(Dyninst::MachRegister reg)
109 {
110    return reg.getDwarfEnc();
111 }
112
113 bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
114                            long int *initialStackValue,
115                            VariableLocation *loc, bool &isLocSet,
116                            ProcessReader *reader,
117                            Dyninst::Architecture arch,
118                            long int &end_result)
119 {
120    /* Initialize the stack. */
121    int addr_width = getArchAddressWidth(arch);
122    std::stack< long int > opStack = std::stack<long int>();
123    if ( initialStackValue != NULL ) { opStack.push( * initialStackValue ); }
124
125    Dwarf_Loc *locations = dwlocs->ld_s;
126    unsigned count = dwlocs->ld_cents;
127    for ( unsigned int i = 0; i < count; i++ ) 
128    {
129       /* Handle the literals w/o 32 case statements. */
130       if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 ) 
131       {
132          dwarf_printf( "pushing named constant: %d\n", locations[i].lr_atom - DW_OP_lit0 );
133          opStack.push( locations[i].lr_atom - DW_OP_lit0 );
134          continue;
135       }
136
137       /* Haandle registers w/o 32 case statements. */
138       if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 ) 
139       {
140          /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
141          dwarf_printf( "location is named register %d\n", 
142                        DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width) );
143          //loc->stClass = storageRegOffset;
144          if (loc) 
145          {
146             loc->stClass = storageReg;
147             loc->refClass = storageNoRef;
148             loc->frameOffset = 0;
149             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
150             //loc->frameOffset = 0;
151             isLocSet = true;
152          }
153          continue;
154       } 
155
156       /* Haandle registers w/o 32 case statements. */
157       if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 ) 
158       {
159          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 );
160          long int to_push;
161          if (loc) {
162             loc->stClass = storageRegOffset;
163             loc->refClass = storageNoRef;
164             loc->frameOffset = locations[i].lr_number ;
165             loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
166             to_push = static_cast<long int>(locations[i].lr_number);
167          }
168          else if (reader) {
169             Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_atom - DW_OP_breg0,
170                                                     arch);
171             Dyninst::MachRegisterVal v;
172             bool result = reader->GetReg(r, v);
173             if (!result) {
174                return false;
175             }
176             to_push = (long int) v + locations[i].lr_number;
177          }
178             
179          opStack.push(to_push); 
180          continue;
181       }
182
183       switch( locations[i].lr_atom ) 
184       {
185          case DW_OP_addr:
186          case DW_OP_const1u:
187          case DW_OP_const2u:
188          case DW_OP_const4u:
189          case DW_OP_const8u:
190          case DW_OP_constu:
191             dwarf_printf( "pushing unsigned constant %lu\n", 
192                           (unsigned long)locations[i].lr_number );
193             opStack.push(static_cast<long int>(locations[i].lr_number));
194             break;
195
196          case DW_OP_const1s:
197          case DW_OP_const2s:
198          case DW_OP_const4s:
199          case DW_OP_const8s:
200          case DW_OP_consts:
201             dwarf_printf( "pushing signed constant %ld\n", 
202                           (signed long)(locations[i].lr_number) );
203             opStack.push(static_cast<long int>(locations[i].lr_number));
204             break;
205
206          case DW_OP_regx:
207             /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
208             dwarf_printf( "location is register %d\n", 
209                           DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width) );
210             if (loc) {
211                loc->stClass = storageReg;
212                loc->refClass = storageNoRef;
213                loc->reg = (int) DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width); 
214                loc->frameOffset = 0;
215                isLocSet = true;
216             }
217             break;
218
219          case DW_OP_fbreg:
220          {
221             dwarf_printf( "setting storage class to frame base\n" );
222             //if ( storageClass != NULL ) { * storageClass = storageFrameOffset; }
223             long int to_push = 0;
224             if (loc) {
225                loc->stClass = storageRegOffset;
226                loc->refClass = storageNoRef;
227                loc->frameOffset = 0;
228                to_push = static_cast<long int>(locations[i].lr_number);
229             }
230             else if (reader) {
231                Dyninst::MachRegister r = Dyninst::FrameBase;
232                Dyninst::MachRegisterVal v;
233                bool result = reader->GetReg(r, v);
234                if (!result) {
235                   return false;
236                }
237                to_push = (long int) v + locations[i].lr_number;               
238             }
239             opStack.push(to_push);
240          } break;          
241          case DW_OP_bregx: 
242          {
243             dwarf_printf( "setting storage class to register, regNum to %d\n", 
244                           locations[i].lr_number );
245             long int to_push = 0;
246             if (loc) {
247                loc->stClass = storageRegOffset;
248                loc->refClass = storageNoRef;
249                loc->reg = (int) DWARF_TO_MACHINE_ENC_W( locations[i].lr_number, addr_width );
250                loc->frameOffset = 0;
251                to_push = static_cast<long int>(locations[i].lr_number2);
252             }
253             else if (reader) {
254                Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_number, arch);
255                Dyninst::MachRegisterVal v;
256                bool result = reader->GetReg(r, v);
257                if (!result) {
258                   return false;
259                }
260                to_push = (long int) v + locations[i].lr_number2;
261             }
262             opStack.push(to_push);
263          } break;
264          case DW_OP_dup:
265             DWARF_FALSE_IF( opStack.size() < 1, 
266                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
267             opStack.push( opStack.top() );
268             break;
269
270          case DW_OP_drop:
271             DWARF_FALSE_IF( opStack.size() < 1, 
272                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
273             opStack.pop();
274             break;
275
276          case DW_OP_pick: 
277          {
278             /* Duplicate the entry at index locations[i].lr_number. */
279             std::stack< long int > temp = std::stack< long int >();
280             
281             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
282             {
283                temp.push( opStack.top() ); opStack.pop();
284             }
285             
286             long int dup = opStack.top();
287             
288             for ( unsigned int j = 0; j < locations[i].lr_number; j++ ) 
289             {
290                opStack.push( temp.top() ); temp.pop();
291             }
292             
293             opStack.push( dup );
294          } break;
295
296          case DW_OP_over: 
297          {
298             DWARF_FALSE_IF( opStack.size() < 2, 
299                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
300             long int first = opStack.top(); opStack.pop();
301             long int second = opStack.top(); opStack.pop();
302             opStack.push( second ); opStack.push( first ); opStack.push( second );
303          } break;
304          
305          case DW_OP_swap: 
306          {
307             DWARF_FALSE_IF( opStack.size() < 2, 
308                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
309             long int first = opStack.top(); opStack.pop();
310             long int second = opStack.top(); opStack.pop();
311             opStack.push( first ); opStack.push( second );
312          } break;
313          
314          case DW_OP_deref:
315          {
316             if (!reader)
317                break;
318             long int addr = opStack.top(); opStack.pop();
319             unsigned long to_push = 0;
320             bool bresult = false;
321             if (addr_width == 4) {
322                uint32_t v;
323                bresult = reader->ReadMem(addr, &v, sizeof(v));
324                to_push = (unsigned long) v;
325             }
326             else if (addr_width == 8) {
327                uint64_t v;
328                bresult = reader->ReadMem(addr, &v, sizeof(v));
329                to_push = (unsigned long) v;
330             }
331             DWARF_FALSE_IF(!bresult,
332                            "%s[%d]: Could not read from %lx\n", addr);
333             opStack.push(to_push);
334             break;
335          }
336          case DW_OP_deref_size:
337          {
338             if (!reader)
339                break;
340             long int addr = opStack.top(); opStack.pop();
341             int width = locations[i].lr_number;
342             unsigned long to_push = 0;
343             bool bresult = false;
344             if (width == 1) {
345                uint8_t v;
346                bresult = reader->ReadMem(addr, &v, sizeof(v));
347                to_push = (unsigned long) v;
348             }
349             if (width == 2) {
350                uint16_t v;
351                bresult = reader->ReadMem(addr, &v, sizeof(v));
352                to_push = (unsigned long) v;
353             }
354             if (width == 4) {
355                uint32_t v;
356                bresult = reader->ReadMem(addr, &v, sizeof(v));
357                to_push = (unsigned long) v;
358             }
359             else if (width == 8) {
360                uint64_t v;
361                bresult = reader->ReadMem(addr, &v, sizeof(v));
362                to_push = (long int) v;
363             }
364             DWARF_FALSE_IF(!bresult,
365                            "%s[%d]: Could not read from %lx\n", addr);
366             opStack.push(to_push);
367             break;
368          }
369          case DW_OP_rot: 
370          {
371             DWARF_FALSE_IF( opStack.size() < 3, 
372                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
373             long int first = opStack.top(); opStack.pop();
374             long int second = opStack.top(); opStack.pop();
375             long int third = opStack.top(); opStack.pop();
376             opStack.push( first ); opStack.push( third ); opStack.push( second );
377          } break;
378
379          case DW_OP_abs: 
380          {
381             DWARF_FALSE_IF( opStack.size() < 1, 
382                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
383             long int top = opStack.top(); opStack.pop();
384             opStack.push( abs( top ) );
385          } break;
386          
387          case DW_OP_and: 
388          {
389             DWARF_FALSE_IF( opStack.size() < 2, 
390                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
391             long int first = opStack.top(); opStack.pop();
392             long int second = opStack.top(); opStack.pop();
393             opStack.push( second & first );
394          } break;
395
396          case DW_OP_div: 
397          {
398             DWARF_FALSE_IF( opStack.size() < 2, 
399                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
400             long int first = opStack.top(); opStack.pop();
401             long int second = opStack.top(); opStack.pop();
402             opStack.push( second / first );
403          } break;
404
405          case DW_OP_minus: 
406          {
407             DWARF_FALSE_IF( opStack.size() < 2, 
408                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
409             long int first = opStack.top(); opStack.pop();
410             long int second = opStack.top(); opStack.pop();
411             opStack.push( second - first );
412          } break;
413
414          case DW_OP_mod: 
415          {
416             DWARF_FALSE_IF( opStack.size() < 2, 
417                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
418             long int first = opStack.top(); opStack.pop();
419             long int second = opStack.top(); opStack.pop();
420             opStack.push( second % first );
421          } break;
422
423          case DW_OP_mul: 
424          {
425             DWARF_FALSE_IF( opStack.size() < 2, 
426                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
427             long int first = opStack.top(); opStack.pop();
428             long int second = opStack.top(); opStack.pop();
429             opStack.push( second * first );
430          } break;
431
432          case DW_OP_neg: 
433          {
434             DWARF_FALSE_IF( opStack.size() < 1, 
435                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
436             long int first = opStack.top(); opStack.pop();
437             opStack.push( first * (-1) );
438          } break;
439          
440          case DW_OP_not: 
441          {
442             DWARF_FALSE_IF( opStack.size() < 1, 
443                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
444             long int first = opStack.top(); opStack.pop();
445             opStack.push( ~ first );
446          } break;
447
448          case DW_OP_or: 
449          {
450             DWARF_FALSE_IF( opStack.size() < 2, 
451                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
452             long int first = opStack.top(); opStack.pop();
453             long int second = opStack.top(); opStack.pop();
454             opStack.push( second | first );
455          } break;
456
457          case DW_OP_plus: 
458          {
459             DWARF_FALSE_IF( opStack.size() < 2, 
460                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
461             long int first = opStack.top(); opStack.pop();
462             long int second = opStack.top(); opStack.pop();
463             opStack.push( second + first );
464          } break;
465
466          case DW_OP_plus_uconst: 
467          {
468             DWARF_FALSE_IF( opStack.size() < 1, 
469                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
470             long int first = opStack.top(); opStack.pop();
471             opStack.push(static_cast<long int>(first + locations[i].lr_number));
472          } break;
473          
474          case DW_OP_shl: 
475          {
476             DWARF_FALSE_IF( opStack.size() < 2, 
477                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
478             long int first = opStack.top(); opStack.pop();
479             long int second = opStack.top(); opStack.pop();
480             opStack.push( second << first );
481          } break;
482
483          case DW_OP_shr: 
484          {
485             DWARF_FALSE_IF( opStack.size() < 2, 
486                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
487             long int first = opStack.top(); opStack.pop();
488             long int second = opStack.top(); opStack.pop();
489             
490             opStack.push( (long int)((unsigned long)second >> (unsigned long)first) );
491          } break;
492          
493          case DW_OP_shra: 
494          {
495             DWARF_FALSE_IF( opStack.size() < 2, 
496                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
497             long int first = opStack.top(); opStack.pop();
498             long int second = opStack.top(); opStack.pop();
499             opStack.push( second >> first );
500          } break;
501
502          case DW_OP_xor: 
503          {
504             DWARF_FALSE_IF( opStack.size() < 2, 
505                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
506             long int first = opStack.top(); opStack.pop();
507             long int second = opStack.top(); opStack.pop();
508             opStack.push( second ^ first );
509          } break;
510
511          case DW_OP_le: 
512          {
513             DWARF_FALSE_IF( opStack.size() < 2, 
514                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
515             long int first = opStack.top(); opStack.pop();
516             long int second = opStack.top(); opStack.pop();
517             opStack.push( first <= second ? 1 : 0 );
518          } break;
519
520          case DW_OP_ge: 
521          {
522             DWARF_FALSE_IF( opStack.size() < 2, 
523                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
524             long int first = opStack.top(); opStack.pop();
525             long int second = opStack.top(); opStack.pop();
526             opStack.push( first >= second ? 1 : 0 );
527          } break;
528
529          case DW_OP_eq: 
530          {
531             DWARF_FALSE_IF( opStack.size() < 2, 
532                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
533             long int first = opStack.top(); opStack.pop();
534             long int second = opStack.top(); opStack.pop();
535             opStack.push( first == second ? 1 : 0 );
536          } break;
537
538          case DW_OP_lt: 
539          {
540             DWARF_FALSE_IF( opStack.size() < 2, 
541                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
542             long int first = opStack.top(); opStack.pop();
543             long int second = opStack.top(); opStack.pop();
544             opStack.push( first < second ? 1 : 0 );
545          } break;
546
547          case DW_OP_gt: 
548          {
549             DWARF_FALSE_IF( opStack.size() < 2, 
550                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
551             long int first = opStack.top(); opStack.pop();
552             long int second = opStack.top(); opStack.pop();
553             opStack.push( first > second ? 1 : 0 );
554          } break;
555
556          case DW_OP_ne: 
557          {
558             DWARF_FALSE_IF( opStack.size() < 2, 
559                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
560             long int first = opStack.top(); opStack.pop();
561             long int second = opStack.top(); opStack.pop();
562             opStack.push( first != second ? 1 : 0 );
563          } break;
564
565          case DW_OP_bra:
566          {
567             DWARF_FALSE_IF( opStack.size() < 1, 
568                             "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
569             if ( opStack.top() == 0 ) { break; }
570             opStack.pop();
571          }
572          case DW_OP_skip: 
573          {
574             int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
575             unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
576             
577             int j = i;
578             if ( bytes < 0 ) {
579                for ( j = i - 1; j >= 0; j-- ) {
580                   if ( locations[j].lr_offset == target ) { break; }
581                } /* end search backward */
582             } else {
583                for ( j = i + 1; j < dwlocs->ld_cents; j ++ ) {
584                   if ( locations[j].lr_offset == target ) { break; }
585                } /* end search forward */
586             } /* end if positive offset */
587             
588             /* Because i will be incremented the next time around the loop. */
589             i = j - 1;
590          } break;
591
592          case DW_OP_piece:
593             /* For multi-part variables, which we don't handle. */
594             //bperr ( "Warning: dyninst does not handle multi-part variables.\n" );
595             break;
596
597          case DW_OP_nop:
598             break;
599
600          default:
601             dwarf_printf( "Unrecognized or non-static location opcode 0x%x, aborting.\n", locations[i].lr_atom );
602             return false;
603             break;
604       } /* end operand switch */
605    } /* end iteration over Dwarf_Loc entries. */
606    
607    if (opStack.empty()) {
608       dwarf_printf( "ignoring malformed location list (stack empty at end of list).\n" );
609       return isLocSet;
610    }
611    dwarf_printf( "Dwarf expression returning %d\n", opStack.top() );
612    end_result = opStack.top();
613    return true;
614 }
615
616 #endif