valgrind/valgrind-3.5.0-dwarf3.patch
Jakub Jelinek 0332e150c8 3.5.0-15
2010-04-07 14:39:29 +00:00

833 lines
30 KiB
Diff

--- valgrind/coregrind/m_debuginfo/readdwarf.c.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/readdwarf.c 2009-10-21 13:18:25.000000000 +0200
@@ -37,6 +37,7 @@
#include "pub_core_libcprint.h"
#include "pub_core_options.h"
#include "pub_core_xarray.h"
+#include "pub_core_tooliface.h" /* VG_(needs) */
#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
#include "priv_d3basics.h"
#include "priv_tytypes.h"
@@ -3446,23 +3447,37 @@ static CIE the_CIEs[N_CIEs];
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe_image )
+ ( /*OUT*/struct _DebugInfo* di, UChar* frame_image, SizeT frame_size,
+ Bool for_eh )
{
Int nbytes;
HChar* how = NULL;
Int n_CIEs = 0;
- UChar* data = ehframe_image;
+ UChar* data = frame_image;
+ UWord ehframe_cfsis = 0;
# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- /* These targets don't use CFI-based stack unwinding. */
- return;
+ if (!VG_(needs).var_info /* the tool requires it */
+ && !VG_(clo_read_var_info) /* the user asked for it */) {
+ /* These targets don't use CFI-based stack unwinding, but still might
+ need it for DW_OP_call_frame_cfa support. */
+ return;
+ }
# endif
+ /* If we are reading .debug_frame after .eh_frame has been read, only
+ add FDEs which weren't covered in .eh_frame. To be able to quickly
+ search the FDEs, the records must be sorted. */
+ if ( ! for_eh && di->ehframe_size && di->cfsi_used ) {
+ ML_(canonicaliseCFI) ( di );
+ ehframe_cfsis = di->cfsi_used;
+ }
+
if (di->trace_cfi) {
VG_(printf)("\n-----------------------------------------------\n");
VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
- di->ehframe_size, di->ehframe_avma,
- ehframe_image );
+ frame_size, for_eh ? di->ehframe_avma : 0,
+ frame_image );
VG_(printf)("CFI info: name %s\n",
di->filename );
}
@@ -3495,11 +3510,11 @@ void ML_(read_callframe_info_dwarf3)
Bool dw64;
/* Are we done? */
- if (data == ehframe_image + di->ehframe_size)
+ if (data == frame_image + frame_size)
return;
/* Overshot the end? Means something is wrong */
- if (data > ehframe_image + di->ehframe_size) {
+ if (data > frame_image + frame_size) {
how = "overran the end of .eh_frame";
goto bad;
}
@@ -3509,9 +3524,9 @@ void ML_(read_callframe_info_dwarf3)
ciefde_start = data;
if (di->trace_cfi)
- VG_(printf)("\ncie/fde.start = %p (ehframe_image + 0x%lx)\n",
+ VG_(printf)("\ncie/fde.start = %p (frame_image + 0x%lx)\n",
ciefde_start,
- ciefde_start - ehframe_image + 0UL);
+ ciefde_start - frame_image + 0UL);
ciefde_len = (ULong) read_UInt(data); data += sizeof(UInt);
if (di->trace_cfi)
@@ -3524,7 +3539,7 @@ void ML_(read_callframe_info_dwarf3)
if (ciefde_len == 0) {
if (di->ddump_frames)
VG_(printf)("%08lx ZERO terminator\n\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image));
+ ((Addr)ciefde_start) - ((Addr)frame_image));
return;
}
@@ -3550,8 +3565,10 @@ void ML_(read_callframe_info_dwarf3)
if (di->trace_cfi)
VG_(printf)("cie.pointer = %lld\n", cie_pointer);
- /* If cie_pointer is zero, we've got a CIE; else it's an FDE. */
- if (cie_pointer == 0) {
+ /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
+ we've got a CIE; else it's an FDE. */
+ if (cie_pointer == (for_eh ? 0ULL
+ : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
Int this_CIE;
UChar cie_version;
@@ -3575,11 +3592,11 @@ void ML_(read_callframe_info_dwarf3)
/* Record its offset. This is how we will find it again
later when looking at an FDE. */
- the_CIEs[this_CIE].offset = (ULong)(ciefde_start - ehframe_image);
+ the_CIEs[this_CIE].offset = (ULong)(ciefde_start - frame_image);
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx CIE\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)frame_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer );
@@ -3623,8 +3640,13 @@ void ML_(read_callframe_info_dwarf3)
VG_(printf)(" Data alignment factor: %d\n",
(Int)the_CIEs[this_CIE].data_a_f);
- the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data);
- data += sizeof(UChar);
+ if (cie_version == 1) {
+ the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data);
+ data += sizeof(UChar);
+ } else {
+ the_CIEs[this_CIE].ra_reg = read_leb128( data, &nbytes, 0);
+ data += nbytes;
+ }
if (di->trace_cfi)
VG_(printf)("cie.ra_reg = %d\n",
the_CIEs[this_CIE].ra_reg);
@@ -3702,7 +3724,7 @@ void ML_(read_callframe_info_dwarf3)
}
if (the_CIEs[this_CIE].ilen < 0
- || the_CIEs[this_CIE].ilen > di->ehframe_size) {
+ || the_CIEs[this_CIE].ilen > frame_size) {
how = "implausible # cie initial insns";
goto bad;
}
@@ -3717,8 +3739,8 @@ void ML_(read_callframe_info_dwarf3)
if (di->trace_cfi || di->ddump_frames) {
AddressDecodingInfo adi;
adi.encoding = the_CIEs[this_CIE].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = for_eh ? di->ehframe_avma : 0;
adi.text_bias = di->text_debug_bias;
show_CF_instructions( the_CIEs[this_CIE].instrs,
the_CIEs[this_CIE].ilen, &adi,
@@ -3747,9 +3769,12 @@ void ML_(read_callframe_info_dwarf3)
cie_pointer bytes back from here. */
/* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
- look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
- - ehframe_image)
- - cie_pointer;
+ if (for_eh)
+ look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
+ - frame_image)
+ - cie_pointer;
+ else
+ look_for = cie_pointer;
for (cie = 0; cie < n_CIEs; cie++) {
if (0) VG_(printf)("look for %lld %lld\n",
@@ -3764,8 +3789,8 @@ void ML_(read_callframe_info_dwarf3)
}
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = for_eh ? di->ehframe_avma : 0;
adi.text_bias = di->text_debug_bias;
fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
data += nbytes;
@@ -3773,8 +3798,8 @@ void ML_(read_callframe_info_dwarf3)
VG_(printf)("fde.initloc = %#lx\n", fde_initloc);
adi.encoding = the_CIEs[cie].address_encoding & 0xf;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = for_eh ? di->ehframe_avma : 0;
adi.text_bias = di->text_debug_bias;
/* WAS (incorrectly):
@@ -3800,7 +3825,7 @@ void ML_(read_callframe_info_dwarf3)
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)frame_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer,
(Addr)look_for,
@@ -3827,16 +3852,43 @@ void ML_(read_callframe_info_dwarf3)
VG_(printf)("fde.ilen = %d\n", (Int)fde_ilen);
}
- if (fde_ilen < 0 || fde_ilen > di->ehframe_size) {
+ if (fde_ilen < 0 || fde_ilen > frame_size) {
how = "implausible # fde insns";
goto bad;
}
data += fde_ilen;
+ if (ehframe_cfsis) {
+ Addr a_mid_lo, a_mid_hi;
+ Word mid, size,
+ lo = 0,
+ hi = ehframe_cfsis-1;
+ while (True) {
+ /* current unsearched space is from lo to hi, inclusive. */
+ if (lo > hi) break; /* not found */
+ mid = (lo + hi) / 2;
+ a_mid_lo = di->cfsi[mid].base;
+ size = di->cfsi[mid].len;
+ a_mid_hi = a_mid_lo + size - 1;
+ vg_assert(a_mid_hi >= a_mid_lo);
+ if (fde_initloc + fde_arange <= a_mid_lo) {
+ hi = mid-1; continue;
+ }
+ if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
+ break;
+ }
+
+ /* The range this .debug_frame FDE covers has been already
+ covered in .eh_frame section. Don't add it from .debug_frame
+ section again. */
+ if (lo <= hi)
+ continue;
+ }
+
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = for_eh ? di->ehframe_avma : 0;
adi.text_bias = di->text_debug_bias;
if (di->trace_cfi)
--- valgrind/coregrind/m_debuginfo/priv_readdwarf.h.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/priv_readdwarf.h 2009-10-21 11:51:38.000000000 +0200
@@ -62,7 +62,7 @@ void ML_(read_debuginfo_dwarf1) ( struct
-------------------- */
extern
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe );
+ ( /*OUT*/struct _DebugInfo* di, UChar* frame, SizeT sz, Bool for_eh );
#endif /* ndef __PRIV_READDWARF_H */
--- valgrind/coregrind/m_debuginfo/priv_d3basics.h.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/priv_d3basics.h 2009-10-21 10:49:47.000000000 +0200
@@ -522,6 +522,9 @@ typedef enum
DW_OP_form_tls_address = 0x9b,
DW_OP_call_frame_cfa = 0x9c,
DW_OP_bit_piece = 0x9d,
+ /* DWARF 4 extensions. */
+ DW_OP_implicit_value = 0x9e,
+ DW_OP_stack_value = 0x9f,
/* GNU extensions. */
DW_OP_GNU_push_tls_address = 0xe0,
/* HP extensions. */
@@ -596,12 +599,13 @@ typedef
/* This describes the result of evaluating a DWARF3 expression.
GXR_Failure: failed; .word is an asciiz string summarising why
+ GXR_Addr: evaluated to an address of the object, in .word
GXR_Value: evaluated to a value, in .word
GXR_RegNo: evaluated to a DWARF3 register number, in .word
*/
typedef
struct {
- enum { GXR_Failure, GXR_Value, GXR_RegNo } kind;
+ enum { GXR_Failure, GXR_Addr, GXR_Value, GXR_RegNo } kind;
UWord word;
}
GXResult;
@@ -644,6 +648,10 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
covered by the guard is also ignored. */
GXResult ML_(evaluate_trivial_GX)( GExpr* gx, const DebugInfo* di );
+/* Compute CFA for IP/SP/FP. */
+Addr ML_(get_CFA) (Addr ip, Addr sp, Addr fp,
+ Addr min_accessible, Addr max_accessible);
+
#endif /* ndef __PRIV_D3BASICS_H */
/*--------------------------------------------------------------------*/
--- valgrind/coregrind/m_debuginfo/readelf.c.jj 2009-10-21 10:49:47.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/readelf.c 2009-10-21 11:52:12.000000000 +0200
@@ -1688,6 +1688,7 @@ Bool ML_(read_elf_debug_info) ( struct _
UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */
UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */
+ UChar* debug_frame_img = NULL; /* .debug_frame (dwarf2) */
UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */
UChar* dwarf1l_img = NULL; /* .line (dwarf1) */
UChar* ehframe_img = NULL; /* .eh_frame (dwarf2) */
@@ -1707,6 +1708,7 @@ Bool ML_(read_elf_debug_info) ( struct _
SizeT debug_str_sz = 0;
SizeT debug_ranges_sz = 0;
SizeT debug_loc_sz = 0;
+ SizeT debug_frame_sz = 0;
SizeT dwarf1d_sz = 0;
SizeT dwarf1l_sz = 0;
SizeT ehframe_sz = 0;
@@ -1764,6 +1766,7 @@ Bool ML_(read_elf_debug_info) ( struct _
FIND(".debug_str", debug_str_sz, debug_str_img)
FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img)
FIND(".debug_loc", debug_loc_sz, debug_loc_img)
+ FIND(".debug_frame", debug_frame_sz, debug_frame_img)
FIND(".debug", dwarf1d_sz, dwarf1d_img)
FIND(".line", dwarf1l_sz, dwarf1l_img)
@@ -1956,6 +1959,8 @@ Bool ML_(read_elf_debug_info) ( struct _
FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
debug_ranges_img)
FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img)
+ FIND(need_dwarf2, ".debug_frame", debug_frame_sz,
+ debug_frame_img)
FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img)
FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img)
@@ -1996,7 +2001,11 @@ Bool ML_(read_elf_debug_info) ( struct _
/* Read .eh_frame (call-frame-info) if any */
if (ehframe_img) {
vg_assert(ehframe_sz == di->ehframe_size);
- ML_(read_callframe_info_dwarf3)( di, ehframe_img );
+ ML_(read_callframe_info_dwarf3)( di, ehframe_img, ehframe_sz, True );
+ }
+ if (debug_frame_sz) {
+ ML_(read_callframe_info_dwarf3)( di, debug_frame_img,
+ debug_frame_sz, False );
}
/* Read the stabs and/or dwarf2 debug information, if any. It
--- valgrind/coregrind/m_debuginfo/priv_storage.h.jj 2009-10-21 10:49:47.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/priv_storage.h 2009-10-21 12:45:31.000000000 +0200
@@ -649,6 +649,8 @@ extern void ML_(addVar)( struct _DebugIn
this after finishing adding entries to these tables. */
extern void ML_(canonicaliseTables) ( struct _DebugInfo* di );
+extern void ML_(canonicaliseCFI) ( struct _DebugInfo* di );
+
/* ------ Searching ------ */
/* Find a symbol-table index containing the specified pointer, or -1
--- valgrind/coregrind/m_debuginfo/storage.c.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/storage.c 2009-10-21 12:44:16.000000000 +0200
@@ -1435,7 +1435,7 @@ static Int compare_DiCfSI ( void* va, vo
return 0;
}
-static void canonicaliseCFI ( struct _DebugInfo* di )
+void ML_(canonicaliseCFI) ( struct _DebugInfo* di )
{
Word i, j;
const Addr minAvma = 0;
@@ -1528,7 +1528,7 @@ void ML_(canonicaliseTables) ( struct _D
{
canonicaliseSymtab ( di );
canonicaliseLoctab ( di );
- canonicaliseCFI ( di );
+ ML_(canonicaliseCFI) ( di );
canonicaliseVarInfo ( di );
}
--- valgrind/coregrind/m_debuginfo/d3basics.c.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/d3basics.c 2009-10-21 13:40:50.000000000 +0200
@@ -443,7 +443,7 @@ static Bool bias_address( Addr* a, const
/* Evaluate a standard DWARF3 expression. See detailed description in
- priv_d3basics.h. */
+ priv_d3basics.h. Doesn't handle DW_OP_piece/DW_OP_bit_piece yet. */
GXResult ML_(evaluate_Dwarf3_Expr) ( UChar* expr, UWord exprszB,
GExpr* fbGX, RegSummary* regs,
const DebugInfo* di,
@@ -482,8 +482,8 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
Addr stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */
GXResult fbval, res;
Addr a1;
- Word sw1;
- UWord uw1;
+ Word sw1, sw2;
+ UWord uw1, uw2;
Bool ok;
sp = -1;
@@ -568,12 +568,15 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
switch (fbval.kind) {
case GXR_Failure:
return fbval; /* propagate failure */
- case GXR_Value:
+ case GXR_Addr:
a1 = fbval.word; break; /* use as-is */
case GXR_RegNo:
ok = get_Dwarf_Reg( &a1, fbval.word, regs );
if (!ok) return fbval; /* propagate failure */
break;
+ case GXR_Value:
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_{implicit,stack}_value "
+ "in DW_AT_frame_base");
default:
vg_assert(0);
}
@@ -599,11 +602,23 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
a1 += sw1;
PUSH( a1 );
break;
+ case DW_OP_bregx:
+ if (!regs)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info");
+ a1 = 0;
+ uw1 = (UWord)read_leb128U( &expr );
+ if (!get_Dwarf_Reg( &a1, uw1, regs ))
+ FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_bregx reg value");
+ sw1 = (Word)read_leb128S( &expr );
+ a1 += sw1;
+ PUSH( a1 );
+ break;
/* As per comment on DW_OP_breg*, the following denote that
the value in question is in a register, not in memory. So
we simply return failure. (iow, the expression is
malformed). */
case DW_OP_reg0 ... DW_OP_reg31:
+ case DW_OP_regx:
FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* "
"whilst evaluating for a value");
break;
@@ -637,6 +652,229 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
"address not valid for client");
}
break;
+ case DW_OP_deref_size:
+ POP(uw1);
+ uw2 = *expr++;
+ if (VG_(am_is_valid_for_client)( (Addr)uw1, uw2,
+ VKI_PROT_READ )) {
+ switch (uw2) {
+ case 1: uw1 = *(UChar*)uw1; break;
+ case 2: uw1 = *(UShort*)uw1; break;
+ case 4: uw1 = *(UInt*)uw1; break;
+ case 8: uw1 = *(ULong*)uw1; break;
+ default:
+ FAIL("warning: evaluate_Dwarf3_Expr: unhandled "
+ "DW_OP_deref_size size");
+ }
+ PUSH(uw1);
+ } else {
+ FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref_size: "
+ "address not valid for client");
+ }
+ break;
+ case DW_OP_lit0 ... DW_OP_lit31:
+ PUSH(opcode - DW_OP_lit0);
+ break;
+ case DW_OP_const1u:
+ uw1 = *expr++;
+ PUSH(uw1);
+ break;
+ case DW_OP_const2u:
+ uw1 = *(UShort *)expr;
+ expr += 2;
+ PUSH(uw1);
+ break;
+ case DW_OP_const4u:
+ uw1 = *(UInt *)expr;
+ expr += 4;
+ PUSH(uw1);
+ break;
+ case DW_OP_const8u:
+ uw1 = *(ULong *)expr;
+ expr += 8;
+ PUSH(uw1);
+ break;
+ case DW_OP_constu:
+ uw1 = read_leb128U( &expr );
+ PUSH(uw1);
+ break;
+ case DW_OP_const1s:
+ uw1 = *(Char *) expr;
+ expr++;
+ PUSH(uw1);
+ break;
+ case DW_OP_const2s:
+ uw1 = *(Short *)expr;
+ expr += 2;
+ PUSH(uw1);
+ break;
+ case DW_OP_const4s:
+ uw1 = *(Int *)expr;
+ expr += 4;
+ PUSH(uw1);
+ break;
+ case DW_OP_const8s:
+ uw1 = *(Long *)expr;
+ expr += 8;
+ PUSH(uw1);
+ break;
+ case DW_OP_consts:
+ uw1 = read_leb128S( &expr );
+ PUSH(uw1);
+ break;
+ case DW_OP_dup:
+ POP(uw1);
+ PUSH(uw1);
+ PUSH(uw1);
+ break;
+ case DW_OP_drop:
+ POP(uw1);
+ break;
+ case DW_OP_over:
+ uw1 = 1;
+ goto do_pick;
+ case DW_OP_pick:
+ uw1 = *expr++;
+ do_pick:
+ if (sp < (Int) uw1)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp - uw1];
+ PUSH(uw1);
+ break;
+ case DW_OP_swap:
+ if (sp < 1)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp];
+ stack[sp] = stack[sp - 1];
+ stack[sp - 1] = uw1;
+ break;
+ case DW_OP_rot:
+ if (sp < 2)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp];
+ stack[sp] = stack[sp - 1];
+ stack[sp - 1] = stack[sp - 2];
+ stack[sp - 2] = uw1;
+ break;
+ case DW_OP_abs:
+ POP(sw1);
+ if (sw1 < 0)
+ sw1 = -sw1;
+ PUSH(sw1);
+ break;
+ case DW_OP_div:
+ POP(sw2);
+ if (sw2 == 0)
+ FAIL("evaluate_Dwarf3_Expr: division by zero");
+ POP(sw1);
+ sw1 /= sw2;
+ PUSH(sw1);
+ break;
+ case DW_OP_mod:
+ POP(sw2);
+ if (sw2 == 0)
+ FAIL("evaluate_Dwarf3_Expr: division by zero");
+ POP(sw1);
+ sw1 %= sw2;
+ PUSH(sw1);
+ break;
+#define BINARY(name, op, s) \
+ case DW_OP_##name: \
+ POP(s##w2); \
+ POP(s##w1); \
+ s##w1 = s##w1 op s##w2; \
+ PUSH(s##w1); \
+ break
+#define UNARY(name, op, s) \
+ case DW_OP_##name: \
+ POP(s##w1); \
+ s##w1 = op s##w1; \
+ PUSH(s##w1); \
+ break
+ BINARY (and, &, u);
+ BINARY (minus, -, u);
+ BINARY (mul, *, u);
+ UNARY (neg, -, u);
+ UNARY (not, ~, u);
+ BINARY (or, |, u);
+ BINARY (plus, +, u);
+ BINARY (shl, <<, u);
+ BINARY (shr, >>, u);
+ BINARY (shra, >>, s);
+ BINARY (xor, ^, u);
+ BINARY (le, <=, s);
+ BINARY (lt, <, s);
+ BINARY (ge, >=, s);
+ BINARY (gt, >, s);
+ BINARY (ne, !=, u);
+ BINARY (eq, ==, u);
+#undef UNARY
+#undef BINARY
+ case DW_OP_skip:
+ sw1 = *(Short *)expr;
+ expr += 2;
+ if (sw1 < 0 && expr < limit - exprszB - sw1)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_skip before start of expr");
+ expr += sw1;
+ break;
+ case DW_OP_bra:
+ sw1 = *(Short *)expr;
+ expr += 2;
+ if (sw1 < 0 && expr < limit - exprszB - sw1)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_bra before start of expr");
+ POP(uw1);
+ if (uw1)
+ expr += sw1;
+ break;
+ case DW_OP_nop:
+ break;
+ case DW_OP_call_frame_cfa:
+ if (!regs)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_call_frame_cfa but no reg info");
+ uw1 = ML_(get_CFA)(regs->ip, regs->sp, regs->fp, 0, ~(UWord) 0);
+ if (!uw1)
+ FAIL("evaluate_Dwarf3_Expr: Could not resolve "
+ "DW_OP_call_frame_cfa");
+ PUSH(uw1);
+ break;
+ case DW_OP_implicit_value:
+ sw1 = (Word)read_leb128S( &expr );
+ uw1 = 0;
+ switch (sw1) {
+ case 1:
+ uw1 = *(UChar *) expr;
+ expr += 1;
+ break;
+ case 2:
+ uw1 = *(UShort *) expr;
+ expr += 2;
+ break;
+ case 4:
+ uw1 = *(UInt *) expr;
+ expr += 4;
+ break;
+ case 8:
+ uw1 = *(ULong *) expr;
+ expr += 8;
+ break;
+ default:
+ FAIL("evaluate_Dwarf3_Expr: Unhandled "
+ "DW_OP_implicit_value size");
+ }
+ if (expr != limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_implicit_value "
+ "does not terminate expression");
+ res.word = uw1;
+ res.kind = GXR_Value;
+ return res;
+ case DW_OP_stack_value:
+ POP (uw1);
+ res.word = uw1;
+ res.kind = GXR_Value;
+ if (expr != limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_stack_value "
+ "does not terminate expression");
+ break;
default:
if (!VG_(clo_xml))
VG_(message)(Vg_DebugMsg,
@@ -650,7 +888,7 @@ GXResult ML_(evaluate_Dwarf3_Expr) ( UCh
vg_assert(sp >= 0 && sp < N_EXPR_STACK);
res.word = stack[sp];
- res.kind = GXR_Value;
+ res.kind = GXR_Addr;
return res;
# undef POP
@@ -829,12 +1067,15 @@ GXResult ML_(evaluate_trivial_GX)( GExpr
if (!badness)
badness = "trivial GExpr denotes register (2)";
}
- else {
+ else if (0) {
VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n ");
ML_(pp_GX)( gx );
VG_(printf)("\n");
tl_assert(0);
}
+ else
+ if (!badness)
+ badness = "non-trivial GExpr";
VG_(addToXA)( results, &thisResult );
@@ -884,7 +1125,7 @@ GXResult ML_(evaluate_trivial_GX)( GExpr
/* Well, we have success. All subexpressions evaluated, and
they all agree. Hurrah. */
- res.kind = GXR_Value;
+ res.kind = GXR_Addr;
res.word = (UWord)mul->ul; /* NB: narrowing from ULong */
VG_(deleteXA)( results );
return res;
@@ -896,6 +1137,8 @@ void ML_(pp_GXResult) ( GXResult res )
switch (res.kind) {
case GXR_Failure:
VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break;
+ case GXR_Addr:
+ VG_(printf)("GXR_Addr(0x%lx)", res.word); break;
case GXR_Value:
VG_(printf)("GXR_Value(0x%lx)", res.word); break;
case GXR_RegNo:
--- valgrind/coregrind/m_debuginfo/debuginfo.c.jj 2009-10-21 10:49:47.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/debuginfo.c 2009-10-21 10:49:47.000000000 +0200
@@ -2003,6 +2003,62 @@ static void cfsi_cache__invalidate ( voi
}
+Addr ML_(get_CFA) (Addr ip, Addr sp, Addr fp,
+ Addr min_accessible, Addr max_accessible )
+{
+ Bool ok;
+ DebugInfo* di;
+ DiCfSI* cfsi = NULL;
+ Addr cfa;
+ CfiExprEvalContext eec;
+ UWord hash = ip % N_CFSI_CACHE;
+ CFSICacheEnt* ce = &cfsi_cache[hash];
+
+ if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
+ /* found an entry in the cache .. */
+ } else {
+ /* not found in cache. Search and update. */
+ ce->ip = ip;
+ find_DiCfSI( &ce->di, &ce->ix, ip );
+ }
+
+ if (UNLIKELY(ce->di == (DebugInfo*)1)) {
+ /* no DiCfSI for this address */
+ return 0;
+ } else {
+ /* found a DiCfSI for this address */
+ di = ce->di;
+ cfsi = &di->cfsi[ ce->ix ];
+ }
+
+ if (UNLIKELY(cfsi == NULL))
+ return 0; /* no info. Nothing we can do. */
+
+ /* Compute the CFA. */
+ cfa = 0;
+ switch (cfsi->cfa_how) {
+ case CFIC_SPREL:
+ cfa = cfsi->cfa_off + sp;
+ break;
+ case CFIC_FPREL:
+ cfa = cfsi->cfa_off + fp;
+ break;
+ case CFIC_EXPR:
+ eec.ipHere = ip;
+ eec.spHere = sp;
+ eec.fpHere = fp;
+ eec.min_accessible = min_accessible;
+ eec.max_accessible = max_accessible;
+ ok = True;
+ cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
+ if (!ok) return 0;
+ break;
+ default:
+ vg_assert(0);
+ }
+ return cfa;
+}
+
/* The main function for DWARF2/3 CFI-based stack unwinding.
Given an IP/SP/FP triple, produce the IP/SP/FP values for the
previous frame, if possible. */
@@ -2346,7 +2402,7 @@ static Bool data_address_is_in_var ( /*O
VG_(printf)("\n");
}
- if (res.kind == GXR_Value
+ if (res.kind == GXR_Addr
&& res.word <= data_addr
&& data_addr < res.word + var_szB) {
*offset = data_addr - res.word;
@@ -3057,7 +3113,7 @@ void analyse_deps ( /*MOD*/XArray* /* of
vg_assert(res_sp_6k.kind == res_fp_6k.kind);
vg_assert(res_sp_6k.kind == res_fp_7k.kind);
- if (res_sp_6k.kind == GXR_Value) {
+ if (res_sp_6k.kind == GXR_Addr) {
StackBlock block;
GXResult res;
UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
@@ -3074,7 +3130,7 @@ void analyse_deps ( /*MOD*/XArray* /* of
regs.sp = regs.fp = 0;
regs.ip = ip;
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
- tl_assert(res.kind == GXR_Value);
+ tl_assert(res.kind == GXR_Addr);
if (debug)
VG_(printf)(" %5ld .. %5ld (sp) %s\n",
res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3093,7 +3149,7 @@ void analyse_deps ( /*MOD*/XArray* /* of
regs.sp = regs.fp = 0;
regs.ip = ip;
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
- tl_assert(res.kind == GXR_Value);
+ tl_assert(res.kind == GXR_Addr);
if (debug)
VG_(printf)(" %5ld .. %5ld (FP) %s\n",
res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3308,7 +3364,7 @@ void* /* really, XArray* of GlobalBlock
res = ML_(evaluate_trivial_GX)( var->gexpr, di );
/* Not a constant address => not interesting */
- if (res.kind != GXR_Value) {
+ if (res.kind != GXR_Addr) {
if (0) VG_(printf)("FAIL\n");
continue;
}
--- valgrind/coregrind/m_debuginfo/tytypes.c.jj 2009-08-19 15:37:44.000000000 +0200
+++ valgrind/coregrind/m_debuginfo/tytypes.c 2009-10-21 10:49:47.000000000 +0200
@@ -766,7 +766,7 @@ XArray* /*UChar*/ ML_(describe_type)( /*
ML_(pp_GXResult)(res);
VG_(printf)("\n");
}
- if (res.kind != GXR_Value)
+ if (res.kind != GXR_Addr)
continue;
mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR );
if (mul.b != True)