--- 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)