833 lines
30 KiB
Diff
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, ®s, 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, ®s, 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)
|