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