2 * Copyright (c) 1996-2011 Barton P. Miller
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.
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.
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.
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.
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
33 #include "dynutil/h/dyn_regs.h"
34 #if !defined(DWARF_EXPR_H)
38 using namespace Dyninst;
40 #if defined(arch_x86_64)
41 // We can only safely map the general purpose registers (0-7 on ia-32,
43 #define IA32_MAX_MAP 7
44 #define AMD64_MAX_MAP 15
45 static int const amd64_register_map[] =
55 8, 9, 10, 11, 12, 13, 14, 15 // gp 8 - 15
56 /* This is incomplete. The x86_64 ABI specifies a mapping from
57 dwarf numbers (0-66) to ("architecture number"). Without a
58 corresponding mapping for the SVR4 dwarf-machine encoding for
59 IA-32, however, it is not meaningful to provide this mapping. */
62 static int Register_DWARFtoMachineEnc32(int n)
64 if (n > IA32_MAX_MAP) {
65 dwarf_printf("%s[%d]: unexpected map lookup for DWARF register %d\n",
72 static int Register_DWARFtoMachineEnc64(int n)
74 if (n <= AMD64_MAX_MAP)
75 return amd64_register_map[n];
77 dwarf_printf("%s[%d]: unexpected map lookup for DWARF register %d\n",
83 #define DWARF_TO_MACHINE_ENC(n, proc) \
84 ((proc->getAddressWidth() == 4) ? Register_DWARFtoMachineEnc32((int) n) : Register_DWARFtoMachineEnc64((int) n))
85 #define DWARF_TO_MACHINE_ENC_W(n, w) \
86 (w == 4) ? Register_DWARFtoMachineEnc32((int) n) : Register_DWARFtoMachineEnc64((int) n)
87 #define DWARF_TO_MACHINEREG_ENC_W(n, w) \
88 (w == 4) ? MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86) : MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86_64);
90 #define DWARF_TO_MACHINE_ENC(n, proc) (n)
91 #define DWARF_TO_MACHINE_ENC_W(n, w) (n)
92 #define DWARF_TO_MACHINEREG_ENC_W(n, w) MachRegister::DwarfEncToReg(n, Dyninst::Arch_x86);
95 #define DWARF_FALSE_IF(condition,...) \
96 if ( condition ) { return false; }
97 #define DWARF_RETURN_IF(condition,...) \
98 if ( condition ) { return; }
99 #define DWARF_NULL_IF(condition,...) \
100 if ( condition ) { return NULL; }
101 #define DWARF_NEXT_IF(condition, ...) \
102 if (condition) { if (depth != 1) { return false; } else {walk_error = true; break; } }
105 static Dyninst::MachRegister DwarfToDynReg(Dwarf_Signed reg, Dyninst::Architecture arch)
107 return MachRegister::DwarfEncToReg(reg, arch);
110 static Dwarf_Signed DynToDwarfReg(Dyninst::MachRegister reg)
112 return reg.getDwarfEnc();
115 static bool decodeDwarfExpression(Dwarf_Locdesc *dwlocs,
116 long int *initialStackValue,
117 VariableLocation *loc, bool &isLocSet,
118 ProcessReader *reader,
119 Dyninst::Architecture arch,
120 long int &end_result)
122 /* Initialize the stack. */
123 int addr_width = getArchAddressWidth(arch);
124 std::stack< long int > opStack = std::stack<long int>();
125 if ( initialStackValue != NULL ) { opStack.push( * initialStackValue ); }
127 Dwarf_Loc *locations = dwlocs->ld_s;
128 unsigned count = dwlocs->ld_cents;
129 for ( unsigned int i = 0; i < count; i++ )
131 /* Handle the literals w/o 32 case statements. */
132 if ( DW_OP_lit0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_lit31 )
134 dwarf_printf( "pushing named constant: %d\n", locations[i].lr_atom - DW_OP_lit0 );
135 opStack.push( locations[i].lr_atom - DW_OP_lit0 );
139 /* Haandle registers w/o 32 case statements. */
140 if ( DW_OP_reg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_reg31 )
142 /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
143 dwarf_printf( "location is named register %d\n",
144 DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width) );
145 //loc->stClass = storageRegOffset;
148 loc->stClass = storageReg;
149 loc->refClass = storageNoRef;
150 loc->frameOffset = 0;
151 loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
152 loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_reg0, addr_width);
153 //loc->frameOffset = 0;
159 /* Haandle registers w/o 32 case statements. */
160 if ( DW_OP_breg0 <= locations[i].lr_atom && locations[i].lr_atom <= DW_OP_breg31 )
162 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 );
165 loc->stClass = storageRegOffset;
166 loc->refClass = storageNoRef;
167 loc->frameOffset = locations[i].lr_number ;
168 loc->reg = DWARF_TO_MACHINE_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
169 loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_atom - DW_OP_breg0, addr_width);
170 to_push = static_cast<long int>(locations[i].lr_number);
173 Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_atom - DW_OP_breg0,
175 Dyninst::MachRegisterVal v;
176 bool result = reader->GetReg(r, v);
180 to_push = (long int) v + locations[i].lr_number;
183 opStack.push(to_push);
187 switch( locations[i].lr_atom )
195 dwarf_printf( "pushing unsigned constant %lu\n",
196 (unsigned long)locations[i].lr_number );
197 opStack.push(static_cast<long int>(locations[i].lr_number));
205 dwarf_printf( "pushing signed constant %ld\n",
206 (signed long)(locations[i].lr_number) );
207 opStack.push(static_cast<long int>(locations[i].lr_number));
211 /* storageReg is unimplemented, so do an offset of 0 from the named register instead. */
212 dwarf_printf( "location is register %d\n",
213 DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width) );
215 loc->stClass = storageReg;
216 loc->refClass = storageNoRef;
217 loc->reg = (int) DWARF_TO_MACHINE_ENC_W(locations[i].lr_number, addr_width);
218 loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W(locations[i].lr_number, addr_width);
219 loc->frameOffset = 0;
226 dwarf_printf( "setting storage class to frame base\n" );
227 //if ( storageClass != NULL ) { * storageClass = storageFrameOffset; }
228 long int to_push = 0;
230 loc->stClass = storageRegOffset;
231 loc->refClass = storageNoRef;
232 loc->frameOffset = 0;
233 to_push = static_cast<long int>(locations[i].lr_number);
236 Dyninst::MachRegister r = Dyninst::FrameBase;
237 Dyninst::MachRegisterVal v;
238 bool result = reader->GetReg(r, v);
242 to_push = (long int) v + locations[i].lr_number;
244 opStack.push(to_push);
248 dwarf_printf( "setting storage class to register, regNum to %d\n",
249 locations[i].lr_number );
250 long int to_push = 0;
252 loc->stClass = storageRegOffset;
253 loc->refClass = storageNoRef;
254 loc->reg = (int) DWARF_TO_MACHINE_ENC_W( locations[i].lr_number, addr_width );
255 loc->mr_reg = DWARF_TO_MACHINEREG_ENC_W( locations[i].lr_number, addr_width );
256 loc->frameOffset = 0;
257 to_push = static_cast<long int>(locations[i].lr_number2);
260 Dyninst::MachRegister r = DwarfToDynReg(locations[i].lr_number, arch);
261 Dyninst::MachRegisterVal v;
262 bool result = reader->GetReg(r, v);
266 to_push = (long int) v + locations[i].lr_number2;
268 opStack.push(to_push);
271 DWARF_FALSE_IF( opStack.size() < 1,
272 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
273 opStack.push( opStack.top() );
277 DWARF_FALSE_IF( opStack.size() < 1,
278 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
284 /* Duplicate the entry at index locations[i].lr_number. */
285 std::stack< long int > temp = std::stack< long int >();
287 for ( unsigned int j = 0; j < locations[i].lr_number; j++ )
289 temp.push( opStack.top() ); opStack.pop();
292 long int dup = opStack.top();
294 for ( unsigned int j = 0; j < locations[i].lr_number; j++ )
296 opStack.push( temp.top() ); temp.pop();
304 DWARF_FALSE_IF( opStack.size() < 2,
305 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
306 long int first = opStack.top(); opStack.pop();
307 long int second = opStack.top(); opStack.pop();
308 opStack.push( second ); opStack.push( first ); opStack.push( second );
313 DWARF_FALSE_IF( opStack.size() < 2,
314 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
315 long int first = opStack.top(); opStack.pop();
316 long int second = opStack.top(); opStack.pop();
317 opStack.push( first ); opStack.push( second );
324 long int addr = opStack.top(); opStack.pop();
325 unsigned long to_push = 0;
326 bool bresult = false;
327 if (addr_width == 4) {
329 bresult = reader->ReadMem(addr, &v, sizeof(v));
330 to_push = (unsigned long) v;
332 else if (addr_width == 8) {
334 bresult = reader->ReadMem(addr, &v, sizeof(v));
335 to_push = (unsigned long) v;
337 DWARF_FALSE_IF(!bresult,
338 "%s[%d]: Could not read from %lx\n", addr);
339 opStack.push(to_push);
342 case DW_OP_deref_size:
346 long int addr = opStack.top(); opStack.pop();
347 int width = locations[i].lr_number;
348 unsigned long to_push = 0;
349 bool bresult = false;
352 bresult = reader->ReadMem(addr, &v, sizeof(v));
353 to_push = (unsigned long) v;
357 bresult = reader->ReadMem(addr, &v, sizeof(v));
358 to_push = (unsigned long) v;
362 bresult = reader->ReadMem(addr, &v, sizeof(v));
363 to_push = (unsigned long) v;
365 else if (width == 8) {
367 bresult = reader->ReadMem(addr, &v, sizeof(v));
368 to_push = (long int) v;
370 DWARF_FALSE_IF(!bresult,
371 "%s[%d]: Could not read from %lx\n", addr);
372 opStack.push(to_push);
377 DWARF_FALSE_IF( opStack.size() < 3,
378 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
379 long int first = opStack.top(); opStack.pop();
380 long int second = opStack.top(); opStack.pop();
381 long int third = opStack.top(); opStack.pop();
382 opStack.push( first ); opStack.push( third ); opStack.push( second );
387 DWARF_FALSE_IF( opStack.size() < 1,
388 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
389 long int top = opStack.top(); opStack.pop();
390 opStack.push( abs( top ) );
395 DWARF_FALSE_IF( opStack.size() < 2,
396 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
397 long int first = opStack.top(); opStack.pop();
398 long int second = opStack.top(); opStack.pop();
399 opStack.push( second & first );
404 DWARF_FALSE_IF( opStack.size() < 2,
405 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
406 long int first = opStack.top(); opStack.pop();
407 long int second = opStack.top(); opStack.pop();
408 opStack.push( second / first );
413 DWARF_FALSE_IF( opStack.size() < 2,
414 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
415 long int first = opStack.top(); opStack.pop();
416 long int second = opStack.top(); opStack.pop();
417 opStack.push( second - first );
422 DWARF_FALSE_IF( opStack.size() < 2,
423 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
424 long int first = opStack.top(); opStack.pop();
425 long int second = opStack.top(); opStack.pop();
426 opStack.push( second % first );
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 );
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) );
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 );
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 );
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 );
472 case DW_OP_plus_uconst:
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));
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 );
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();
496 opStack.push( (long int)((unsigned long)second >> (unsigned long)first) );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
573 DWARF_FALSE_IF( opStack.size() < 1,
574 "%s[%d]: invalid stack, returning false.\n", __FILE__, __LINE__ );
575 if ( opStack.top() == 0 ) { break; }
580 int bytes = (int)(Dwarf_Signed)locations[i].lr_number;
581 unsigned int target = (unsigned int) locations[i].lr_offset + bytes;
585 for ( j = i - 1; j >= 0; j-- ) {
586 if ( locations[j].lr_offset == target ) { break; }
587 } /* end search backward */
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 */
594 /* Because i will be incremented the next time around the loop. */
599 /* For multi-part variables, which we don't handle. */
600 //bperr ( "Warning: dyninst does not handle multi-part variables.\n" );
607 dwarf_printf( "Unrecognized or non-static location opcode 0x%x, aborting.\n", locations[i].lr_atom );
610 } /* end operand switch */
611 } /* end iteration over Dwarf_Loc entries. */
613 if (opStack.empty()) {
614 dwarf_printf( "ignoring malformed location list (stack empty at end of list).\n" );
617 dwarf_printf( "Dwarf expression returning %d\n", opStack.top() );
618 end_result = opStack.top();