|
From: <sv...@va...> - 2005-04-30 18:47:54
|
Author: sewardj
Date: 2005-04-30 19:47:48 +0100 (Sat, 30 Apr 2005)
New Revision: 3582
Modified:
trunk/coregrind/core.h
trunk/coregrind/m_stacktrace.c
trunk/coregrind/pub_core_stacktrace.h
trunk/coregrind/vg_dwarf.c
trunk/coregrind/vg_main.c
trunk/coregrind/vg_mylibc.c
trunk/coregrind/vg_signals.c
trunk/coregrind/vg_symtab2.c
trunk/coregrind/vg_symtab2.h
Log:
Get the CFI-based frame-unwinder to the point where it works at least
for small examples on x86. Still messy, slow, amd64 specifics not
done, and non-null cie.augmentations are not handled.
Modified: trunk/coregrind/core.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/core.h 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/core.h 2005-04-30 18:47:48 UTC (rev 3582)
@@ -882,6 +882,13 @@
=20
extern Bool VG_(resolve_redir_allsegs)(CodeRedirect *redir);
=20
+extern Bool VG_(use_CFI_info) ( /*MOD*/Addr* ipP,
+ /*MOD*/Addr* spP,
+ /*MOD*/Addr* fpP,
+ Addr min_accessible,
+ Addr max_accessible );
+
+
/* ---------------------------------------------------------------------
Exports of vg_redir.c
------------------------------------------------------------------ */
Modified: trunk/coregrind/m_stacktrace.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_stacktrace.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/m_stacktrace.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -38,7 +38,8 @@
/* Take a snapshot of the client's stack, putting the up to 'n_ips' IPs=20
into 'ips'. In order to be thread-safe, we pass in the thread's IP
and FP. Returns number of IPs put in 'ips'. */
-UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, Addr ip, Addr fp,
+UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,=20
+ Addr ip, Addr sp, Addr fp,
Addr fp_min, Addr fp_max_orig )
{
static const Bool debug =3D False;
@@ -72,32 +73,57 @@
* offending stack traces only have one item. --njn, 2002-aug-16 */
/* vg_assert(fp_min <=3D fp_max);*/
=20
- if (fp_min + 4000000 <=3D fp_max) {
+ ips[0] =3D ip;
+ i =3D 1;
+
+ if (fp_min + VG_(clo_max_stackframe) <=3D fp_max) {
/* If the stack is ridiculously big, don't poke around ... but
don't bomb out either. Needed to make John Regehr's
user-space threads package work. JRS 20021001 */
- ips[0] =3D ip;
- i =3D 1;
} else {
- /* Get whatever we safely can ... */
- ips[0] =3D ip;
- fp =3D VGA_FIRST_STACK_FRAME(fp);
- for (i =3D 1; i < n_ips; i++) {
- if (!(fp_min <=3D fp && fp <=3D fp_max)) {
- if (debug)
- VG_(printf)("... out of range %p\n", fp);
- break; /* fp gone baaaad */
- }
- // NJN 2002-sep-17: monotonicity doesn't work -- gives wrong tr=
aces...
- // if (fp >=3D ((UInt*)fp)[0]) {
- // VG_(printf)("nonmonotonic\n");
- // break; /* fp gone nonmonotonic */
- // }
- ips[i] =3D VGA_STACK_FRAME_RET(fp); /* ret addr */
- fp =3D VGA_STACK_FRAME_NEXT(fp); /* old fp */
- if (debug)
- VG_(printf)(" ips[%d]=3D%08p\n", i, ips[i]);
+
+ while (True) {
+
+ if (i >=3D n_ips)
+ break;
+
+ /* Try to derive a new (ip,sp,fp) triple from the current
+ set. */
+
+ /* First off, see if there is any CFI info to hand which can
+ be used. */
+ if ( VG_(use_CFI_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+ ips[i++] =3D ip;
+ if (debug)
+ VG_(printf)(" ipsC[%d]=3D%08p\n", i-1, ips[i-1]);
+ continue;
+ }
+
+ /* If VG_(use_CFI_info) fails, it won't modify ip/sp/fp, so
+ we can safely try the old-fashioned method. */
+ /* This bit is supposed to deal with frames resulting from
+ functions which begin "pushl% ebp ; movl %esp, %ebp" (x86)
+ or "pushl% ebp ; movl %esp, %ebp" (amd64). Unfortunately,
+ since we can't (easily) look at the insns at the start of
+ the fn, like GDB does, there's no reliable way to tell.
+ Hence the hack of first trying out CFI, and if that fails,
+ then use this as a fallback. */
+ if (fp_min <=3D fp && fp <=3D fp_max) {
+ /* fp looks sane, so use it. */
+ ip =3D VGA_STACK_FRAME_RET(fp);
+ sp =3D fp + sizeof(Addr) /*saved %ebp/%rbp*/=20
+ + sizeof(Addr) /*ra*/;
+ fp =3D VGA_STACK_FRAME_NEXT(fp);
+ ips[i++] =3D ip;
+ if (debug)
+ VG_(printf)(" ipsF[%d]=3D%08p\n", i-1, ips[i-1]);
+ continue;
+ }
+
+ /* No luck there. We have to give up. */
+ break;
}
+
}
n_found =3D i;
=20
@@ -139,7 +165,7 @@
VG_(printf)("tid %d: stack_highest=3D%p ip=3D%p sp=3D%p fp=3D%p\n"=
,
tid, stack_highest_word, ip, sp, fp);
=20
- return VG_(get_StackTrace2)(ips, n_ips, ip, fp, sp, stack_highest_wor=
d);
+ return VG_(get_StackTrace2)(ips, n_ips, ip, sp, fp, sp, stack_highest=
_word);
}
=20
static void printIpDesc(UInt n, Addr ip)
Modified: trunk/coregrind/pub_core_stacktrace.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_stacktrace.h 2005-04-30 07:55:58 UTC (rev 35=
81)
+++ trunk/coregrind/pub_core_stacktrace.h 2005-04-30 18:47:48 UTC (rev 35=
82)
@@ -39,8 +39,9 @@
#include "pub_tool_stacktrace.h"
=20
// Variant that gives a little more control over the stack-walking.
-extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips, Addr ip,
- Addr fp, Addr fp_min, Addr fp_max );
+extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips,=20
+ Addr ip, Addr sp, Addr fp,=20
+ Addr fp_min, Addr fp_max );
=20
#endif // __PUB_CORE_STACKTRACE_H
=20
Modified: trunk/coregrind/vg_dwarf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_dwarf.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_dwarf.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -829,6 +829,87 @@
/*--- Read call-frame info from an .eh_frame section ---*/
/*------------------------------------------------------------*/
=20
+void VG_(ppCfiSI) ( CfiSI* si )
+{
+# define SHOW_HOW(_how, _off) \
+ do { \
+ if (_how =3D=3D CFIR_UNKNOWN) { \
+ VG_(printf)("Unknown"); \
+ } else \
+ if (_how =3D=3D CFIR_SAME) { \
+ VG_(printf)("Same"); \
+ } else \
+ if (_how =3D=3D CFIR_CFAREL) { \
+ VG_(printf)("cfa+%d", _off); \
+ } else \
+ if (_how =3D=3D CFIR_MEMCFAREL) { \
+ VG_(printf)("*(cfa+%d)", _off); \
+ } else { \
+ VG_(printf)("???"); \
+ } \
+ } while (0)
+
+ VG_(printf)("[%p .. %p]: ", si->base,=20
+ si->base + (UWord)si->len - 1);
+ VG_(printf)("let cfa=3D%s+%d",=20
+ si->cfa_sprel ? "oldSP" : "oldFP", si->cfa_off);
+ VG_(printf)(" in RA=3D");
+ SHOW_HOW(si->ra_how, si->ra_off);
+ VG_(printf)(" SP=3D");
+ SHOW_HOW(si->sp_how, si->sp_off);
+ VG_(printf)(" FP=3D");
+ SHOW_HOW(si->fp_how, si->fp_off);
+ VG_(printf)("\n");
+
+# undef SHOW_HOW
+}
+
+static void initCfiSI ( CfiSI* si )
+{
+ si->base =3D 0;
+ si->len =3D 0;
+ si->cfa_sprel =3D False;
+ si->ra_how =3D 0;
+ si->sp_how =3D 0;
+ si->fp_how =3D 0;
+ si->cfa_off =3D 0;
+ si->ra_off =3D 0;
+ si->sp_off =3D 0;
+ si->fp_off =3D 0;
+}
+
+
+/* Useful info ..
+
+ gdb-6.3/gdb/i386-tdep.c:
+
+ DWARF2/GCC uses the stack address *before* the function call as a
+ frame's CFA. [jrs: I presume this means %esp before the call as
+ the CFA].=20
+
+ JRS: on amd64, the dwarf register numbering is, as per
+ gdb-6.3/gdb/tdep-amd64.c and also amd64-abi-0.95.pdf:
+
+ 0 1 2 3 4 5 6 7
+ RAX RDX RCX RBX RSI RDI RBP RSP
+
+ 8 ... 15
+ R8 ... R15
+
+ 16 is the return address (RIP)
+
+ This is pretty strange given this not the encoding scheme for
+ registers used in amd64 code.
+
+ On x86 I cannot find any documentation. It _appears_ to be the
+ actual instruction encoding, viz:
+
+ 0 1 2 3 4 5 6 7
+ EAX ECX EDX EBX ESP EBP ESI EDI
+
+ 8 is the return address (EIP) */
+
+
/* the number of regs we are prepared to unwind */
#define N_CFI_REGS 20
=20
@@ -879,8 +960,9 @@
typedef
struct {
/* Read-only fields. */
- Int code_a_f;
- Int data_a_f;
+ Int code_a_f;
+ Int data_a_f;
+ Addr initloc;
/* The rest of these fields can be modifed by
run_CF_instruction. */
/* The LOC entry */
@@ -908,21 +990,113 @@
}
}
=20
+static void ppRegRule ( RegRule* reg )
+{
+ switch (reg->tag) {
+ case RR_Undef: VG_(printf)("u "); break;
+ case RR_Same: VG_(printf)("s "); break;
+ case RR_CFAoff: VG_(printf)("c%d ", reg->coff); break;
+ case RR_Reg: VG_(printf)("r%d ", reg->reg); break;
+ case RR_Arch: VG_(printf)("a "); break;
+ default: VG_(core_panic)("ppRegRule");
+ }
+}
+
+
static void ppUnwindContext ( UnwindContext* ctx )
{
Int i;
VG_(printf)("0x%llx: ", (ULong)ctx->loc);
VG_(printf)("%d(r%d) ", ctx->cfa_offset, ctx->cfa_reg);
- for (i =3D 0; i < N_CFI_REGS; i++) {
- switch (ctx->reg[i].tag) {
- case RR_Undef: VG_(printf)("u "); break;
- case RR_Same: VG_(printf)("s "); break;
- case RR_CFAoff: VG_(printf)("c%d ", ctx->reg[i].coff); break;
- case RR_Reg: VG_(printf)("r%d ", ctx->reg[i].reg); break;
- case RR_Arch: VG_(printf)("a "); break;
- default: VG_(core_panic)("ppUnwindContext");
- }
+ for (i =3D 0; i < N_CFI_REGS; i++)
+ ppRegRule(&ctx->reg[i]);
+ VG_(printf)("\n");
+}
+
+
+/* Summarise ctx into si, if possible. Returns True if successful.
+ This is taken to be just after ctx's loc advances; hence the
+ summary is up to but not including the current loc.
+*/
+static Bool summarise_context_x86 ( /*OUT*/CfiSI* si,
+ Addr loc_start,
+ UnwindContext* ctx )
+{
+ initCfiSI(si);
+
+ /* How to generate the CFA */
+ if (ctx->cfa_reg =3D=3D 4 /* ESP */) {
+ si->cfa_sprel =3D True;
+ si->cfa_off =3D ctx->cfa_offset;
+ } else
+ if (ctx->cfa_reg =3D=3D 5 /* EBP */) {
+ si->cfa_sprel =3D False;
+ si->cfa_off =3D ctx->cfa_offset;
+ } else {
+ goto failed;
}
+
+# define SUMMARISE_HOW(_how, _off, _ctxreg) =
\
+ switch (_ctxreg.tag) { =
\
+ case RR_Undef: _how =3D CFIR_UNKNOWN; _off =3D 0; break; =
\
+ case RR_Same: _how =3D CFIR_SAME; _off =3D 0; break; =
\
+ case RR_CFAoff: _how =3D CFIR_MEMCFAREL; _off =3D _ctxreg.coff; br=
eak; \
+ default: goto failed; /* otherwise give up */ =
\
+ }
+
+ SUMMARISE_HOW(si->ra_how, si->ra_off, ctx->reg[8 /* Return address */=
] );
+ SUMMARISE_HOW(si->fp_how, si->fp_off, ctx->reg[5 /* EBP */] );
+
+# undef SUMMARISE_HOW
+
+ /* on x86, it seems the old %esp value before the call is always
+ the same as the CFA. Therefore ... */
+ si->sp_how =3D CFIR_CFAREL;
+ si->sp_off =3D 0;
+
+ /* also, gcc says "Undef" for %ebp when it is unchanged. So .. */
+ if (ctx->reg[5 /* EBP */].tag =3D=3D RR_Undef)
+ si->fp_how =3D CFIR_SAME;
+
+ /* knock out some obviously stupid cases */
+ if (si->ra_how =3D=3D CFIR_SAME) goto failed;
+
+ /* bogus looking range? Note, we require that the difference is
+ representable in 32 bits. */
+ if (loc_start >=3D ctx->loc) goto failed;
+ if (ctx->loc - loc_start > 10000000 /* let's say */)
+ goto failed;
+
+ si->base =3D loc_start + ctx->initloc;
+ si->len =3D (UInt)(ctx->loc - loc_start);
+
+ return True;
+
+ failed:
+ VG_(printf)("summarise_context_x86(loc_start =3D %p)"
+ ": cannot summarise:\n ", loc_start);
+ ppUnwindContext(ctx);
+ return False;
+}
+
+static void ppUnwindContext_x86_summary ( UnwindContext* ctx )
+{
+ VG_(printf)("0x%llx-1: ", (ULong)ctx->loc);
+
+ if (ctx->cfa_reg =3D=3D 4 /* ESP */) {
+ VG_(printf)("SP/CFA=3D%d+%%esp ", ctx->cfa_offset);
+ } else
+ if (ctx->cfa_reg =3D=3D 5 /* EBP */) {
+ VG_(printf)("SP/CFA=3D%d+%%ebp ", ctx->cfa_offset);
+ } else {
+ VG_(printf)("SP/CFA=3Dunknown ", ctx->cfa_offset);
+ }
+
+ VG_(printf)("RA=3D");
+ ppRegRule( &ctx->reg[8 /* Return address */] );
+
+ VG_(printf)("FP=3D");
+ ppRegRule( &ctx->reg[5 /* EBP */] );
VG_(printf)("\n");
}
=20
@@ -1145,19 +1319,38 @@
reached, or until there is a failure. Return True iff success.=20
*/
static=20
-Bool run_CF_instructions ( UnwindContext* ctx, UChar* instrs, Int ilen )
+Bool run_CF_instructions ( SegInfo* si,
+ UnwindContext* ctx, UChar* instrs, Int ilen,
+ UWord fde_arange )
{
+ CfiSI cfisi;
+
Int j, i =3D 0;
- ppUnwindContext(ctx);
+ Addr loc_prev;
+ if (0) ppUnwindContext(ctx);
+ if (0) ppUnwindContext_x86_summary(ctx);
while (True) {
+ loc_prev =3D ctx->loc;
if (i >=3D ilen) break;
if (0) (void)show_CF_instruction( &instrs[i] );
j =3D run_CF_instruction( ctx, &instrs[i] );
if (j =3D=3D 0)
return False; /* execution failed */
i +=3D j;
- ppUnwindContext(ctx);
+ if (0) ppUnwindContext(ctx);
+ if (loc_prev !=3D ctx->loc && si) {
+ summarise_context_x86 ( &cfisi, loc_prev, ctx );
+ VG_(addCfiSI)(si, &cfisi);
+ }
}
+ if (ctx->loc < fde_arange) {
+ loc_prev =3D ctx->loc;
+ ctx->loc =3D fde_arange;
+ if (si) {
+ summarise_context_x86 ( &cfisi, loc_prev, ctx );
+ VG_(addCfiSI)(si, &cfisi);
+ }
+ }
return True;
}
=20
@@ -1174,8 +1367,8 @@
=20
UChar* current_cie =3D NULL;
=20
- if (ehframe_sz !=3D 240) return;
- VG_(printf)("\n\n\neh_frame %p %d\n", ehframe, ehframe_sz);
+ if (0&& ehframe_sz !=3D 240) return;
+ if (0) VG_(printf)("\n\n\neh_frame %p %d\n", ehframe, ehframe_sz);
=20
UChar* data =3D ehframe;
=20
@@ -1200,10 +1393,10 @@
Figure out which it is. */
=20
UChar* ciefde_start =3D data;
- VG_(printf)("\ncie/fde.start =3D %p\n", ciefde_start);
+ if (0) VG_(printf)("\ncie/fde.start =3D %p\n", ciefde_start);
=20
UInt ciefde_len =3D read_UInt(data); data +=3D sizeof(UInt);
- VG_(printf)("cie/fde.length =3D %d\n", ciefde_len);
+ if (0) VG_(printf)("cie/fde.length =3D %d\n", ciefde_len);
=20
/* Apparently, if the .length field is zero, we are at the end
of the sequence. ?? Neither the DWARF2 spec not the AMD64
@@ -1216,7 +1409,7 @@
}
=20
UInt cie_pointer =3D read_UInt(data); data +=3D sizeof(UInt);
- VG_(printf)("cie.pointer =3D %d\n", cie_pointer);
+ if (0) VG_(printf)("cie.pointer =3D %d\n", cie_pointer);
=20
/* If cie_pointer is zero, we've got a CIE; else it's an FDE. */
if (cie_pointer =3D=3D 0) {
@@ -1226,11 +1419,11 @@
=20
/* --------- CIE --------- */
UChar cie_version =3D read_UChar(data); data +=3D sizeof(UChar)=
;
- VG_(printf)("cie.version =3D %d\n", (Int)cie_version);
+ if (0) VG_(printf)("cie.version =3D %d\n", (Int)cie_version=
);
=20
UChar* cie_augmentation =3D data;
data +=3D 1 + VG_(strlen)(cie_augmentation);
- VG_(printf)("cie.augment =3D \"%s\"\n", cie_augmentation);
+ if (0) VG_(printf)("cie.augment =3D \"%s\"\n", cie_augmenta=
tion);
=20
if (0 !=3D VG_(strcmp)(cie_augmentation, "")) {
how =3D "non-NULL cie.augmentation";
@@ -1239,19 +1432,19 @@
=20
cie_codeaf =3D read_leb128( data, &nbytes, 0);
data +=3D nbytes;
- VG_(printf)("cie.code_af =3D %d\n", cie_codeaf);
+ if (0) VG_(printf)("cie.code_af =3D %d\n", cie_codeaf);
=20
cie_dataaf =3D read_leb128( data, &nbytes, 1);
data +=3D nbytes;
- VG_(printf)("cie.data_af =3D %d\n", cie_dataaf);
+ if (0) VG_(printf)("cie.data_af =3D %d\n", cie_dataaf);
=20
UChar cie_rareg =3D read_UChar(data); data +=3D sizeof(UChar);
- VG_(printf)("cie.ra_reg =3D %d\n", (Int)cie_rareg);
+ if (0) VG_(printf)("cie.ra_reg =3D %d\n", (Int)cie_rareg);
=20
cie_instrs =3D data;
cie_ilen =3D ciefde_start + ciefde_len + sizeof(UInt) - data;
- VG_(printf)("cie.instrs =3D %p\n", (Int)cie_instrs);
- VG_(printf)("cie.ilen =3D %d\n", (Int)cie_ilen);
+ if (0) VG_(printf)("cie.instrs =3D %p\n", (Int)cie_instrs)=
;
+ if (0) VG_(printf)("cie.ilen =3D %d\n", (Int)cie_ilen);
=20
if (cie_ilen < 0 || cie_ilen > ehframe_sz) {
how =3D "implausible # cie initial insns";
@@ -1260,33 +1453,33 @@
=20
data +=3D cie_ilen;
=20
- show_CF_instructions(cie_instrs, cie_ilen);
+ if (0) show_CF_instructions(cie_instrs, cie_ilen);
=20
} else {
=20
/* --------- FDE --------- */
=20
- /* Ensure that (1) we have a valid CIE, and (2) that=20
- it is indeed the CIE referred to by this FDE. */
- if (current_cie =3D=3D NULL) {
- how =3D "FDE with no preceding CIE";
- goto bad;
- }
- if (cie_pointer !=3D data - current_cie) {
- how =3D "FDE does not refer to preceding CIE";
- goto bad;
- }
+ /* Ensure that (1) we have a valid CIE, and (2) that it is
+ indeed the CIE referred to by this FDE. */
+ if (current_cie =3D=3D NULL) {
+ how =3D "FDE with no preceding CIE";
+ goto bad;
+ }
+ if (cie_pointer !=3D data - current_cie) {
+ how =3D "FDE does not refer to preceding CIE";
+ goto bad;
+ }
=20
Addr fde_initloc =3D read_Addr(data); data +=3D sizeof(Addr);
- VG_(printf)("fde.initloc =3D %p\n", (void*)fde_initloc);
+ if (0) VG_(printf)("fde.initloc =3D %p\n", (void*)fde_initl=
oc);
=20
UWord fde_arange =3D read_Addr(data); data +=3D sizeof(Addr);
- VG_(printf)("fde.arangec =3D %p\n", (void*)fde_arange);
+ if (0) VG_(printf)("fde.arangec =3D %p\n", (void*)fde_arang=
e);
=20
UChar* fde_instrs =3D data;
Int fde_ilen =3D ciefde_start + ciefde_len + sizeof(UInt) =
- data;
- VG_(printf)("fde.instrs =3D %p\n", (Int)fde_instrs);
- VG_(printf)("fde.ilen =3D %d\n", (Int)fde_ilen);
+ if (0) VG_(printf)("fde.instrs =3D %p\n", (Int)fde_instrs)=
;
+ if (0) VG_(printf)("fde.ilen =3D %d\n", (Int)fde_ilen);
=20
if (fde_ilen < 0 || fde_ilen > ehframe_sz) {
how =3D "implausible # fde initial insns";
@@ -1298,20 +1491,17 @@
initUnwindContext(&ctx);
ctx.code_a_f =3D cie_codeaf;
ctx.data_a_f =3D cie_dataaf;
- ok =3D run_CF_instructions(&ctx, cie_instrs, cie_ilen);
+ ctx.initloc =3D fde_initloc;
+ ok =3D run_CF_instructions(NULL, &ctx, cie_instrs, cie_ilen, 0);
if (ok)
- ok =3D run_CF_instructions(&ctx, fde_instrs, fde_ilen);
+ ok =3D run_CF_instructions(si, &ctx, fde_instrs, fde_ilen, fde_aran=
ge);
}
}
=20
- /* Read a CIE and remember important bits */
-
-
-
return;
=20
bad:
- VG_(message)(Vg_UserMsg, "Warning: %s in DWARF2 CIE reading", how);
+ VG_(message)(Vg_UserMsg, "Warning: %s in DWARF2 CFI reading", how);
return;
}
=20
Modified: trunk/coregrind/vg_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_main.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_main.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -1588,7 +1588,7 @@
properly really entails getting rid of the circularity between
the two memory allocators, but that is more than I have time to
sort out right now. */
- VG_(clo_vex_control).guest_chase_thresh =3D 0;
+ // VG_(clo_vex_control).guest_chase_thresh =3D 0;
=20
/* parse the options we have (only the options we care about now) */
for (i =3D 1; i < vg_argc; i++) {
Modified: trunk/coregrind/vg_mylibc.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_mylibc.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_mylibc.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -902,7 +902,7 @@
tst->os_state.valgrind_stack_szB;
=20
VG_(get_StackTrace2)(ips, VG_(clo_backtrace_size),
- ret, fp, sp, stacktop);
+ ret, sp, fp, sp, stacktop);
VG_(pp_StackTrace) (ips, VG_(clo_backtrace_size));
}
=20
Modified: trunk/coregrind/vg_signals.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_signals.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_signals.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -1943,6 +1943,7 @@
tst =3D VG_(get_ThreadState)(tid);
VG_(get_StackTrace2)(ips, VG_(clo_backtrace_size),=20
VGP_UCONTEXT_INSTR_PTR(uc),
+ VGP_UCONTEXT_STACK_PTR(uc),
VGP_UCONTEXT_FRAME_PTR(uc),
VGP_UCONTEXT_STACK_PTR(uc),
tst->os_state.valgrind_stack_base +=20
Modified: trunk/coregrind/vg_symtab2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_symtab2.c 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_symtab2.c 2005-04-30 18:47:48 UTC (rev 3582)
@@ -369,6 +369,40 @@
addScopeRange ( si, &range );
}
=20
+
+/* Top-level place to call to add a CFI summary record. The supplied
+ CfiSI is copied. */
+void VG_(addCfiSI) ( SegInfo* si, CfiSI* cfisi )
+{
+ static const Bool debug =3D False;
+
+ if (debug) {
+ VG_(printf)("adding CfiSI: ");
+ VG_(ppCfiSI)(cfisi);
+ }
+
+ UInt new_sz, i;
+ CfiSI* new_tab;
+
+ if (si->cfisi_used =3D=3D si->cfisi_size) {
+ new_sz =3D 2 * si->cfisi_size;
+ if (new_sz =3D=3D 0) new_sz =3D 20;
+ new_tab =3D VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(CfiSI)=
);
+ if (si->cfisi !=3D NULL) {
+ for (i =3D 0; i < si->cfisi_used; i++)
+ new_tab[i] =3D si->cfisi[i];
+ VG_(arena_free)(VG_AR_SYMTAB, si->cfisi);
+ }
+ si->cfisi =3D new_tab;
+ si->cfisi_size =3D new_sz;
+ }
+
+ si->cfisi[si->cfisi_used] =3D *cfisi;
+ si->cfisi_used++;
+ vg_assert(si->cfisi_used <=3D si->cfisi_size);
+}
+
+
/*------------------------------------------------------------*/
/*--- Helpers ---*/
/*------------------------------------------------------------*/
@@ -2276,6 +2310,82 @@
#undef APPEND
}
=20
+/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
+
+Bool VG_(use_CFI_info) ( /*MOD*/Addr* ipP,
+ /*MOD*/Addr* spP,
+ /*MOD*/Addr* fpP,
+ Addr min_accessible,
+ Addr max_accessible )
+{
+ Int i;
+ SegInfo* si;
+ CfiSI* cfisi =3D NULL;
+ Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+
+ if (0) VG_(printf)("search for %p\n", *ipP);
+
+ for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (i =3D 0; i < si->cfisi_used; i++) {
+ if (si->cfisi[i].base <=3D *ipP
+ && *ipP < si->cfisi[i].base+si->cfisi[i].len) {
+ cfisi =3D &si->cfisi[i];
+ goto postloop;
+ }
+ }
+ }
+
+ postloop:
+ if (cfisi =3D=3D NULL)
+ return False;
+
+ if (0) {
+ VG_(printf)("found cfisi: ");=20
+ VG_(ppCfiSI)(cfisi);
+ }
+
+ ipPrev =3D spPrev =3D fpPrev =3D 0;
+
+ ipHere =3D *ipP;
+ spHere =3D *spP;
+ fpHere =3D *fpP;
+
+ cfa =3D cfisi->cfa_off + (cfisi->cfa_sprel ? spHere : fpHere);
+
+# define COMPUTE(_prev, _here, _how, _off) \
+ do { \
+ switch (_how) { \
+ case CFIR_UNKNOWN: \
+ return False; \
+ case CFIR_SAME: \
+ _prev =3D _here; break; \
+ case CFIR_MEMCFAREL: { \
+ Addr a =3D cfa + (Word)_off; \
+ if (a < min_accessible \
+ || a+sizeof(Addr) > max_accessible) \
+ return False; \
+ _prev =3D *(Addr*)a; \
+ break; \
+ } \
+ case CFIR_CFAREL: \
+ _prev =3D cfa + (Word)_off; \
+ break; \
+ } \
+ } while (0)
+
+ COMPUTE(ipPrev, ipHere, cfisi->ra_how, cfisi->ra_off);
+ COMPUTE(spPrev, spHere, cfisi->sp_how, cfisi->sp_off);
+ COMPUTE(fpPrev, fpHere, cfisi->fp_how, cfisi->fp_off);
+
+# undef COMPUTE
+
+ *ipP =3D ipPrev;
+ *spP =3D spPrev;
+ *fpP =3D fpPrev;
+ return True;
+}
+
+
/*------------------------------------------------------------*/
/*--- SegInfo accessor functions ---*/
/*------------------------------------------------------------*/
Modified: trunk/coregrind/vg_symtab2.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/vg_symtab2.h 2005-04-30 07:55:58 UTC (rev 3581)
+++ trunk/coregrind/vg_symtab2.h 2005-04-30 18:47:48 UTC (rev 3582)
@@ -118,20 +118,50 @@
#define STRCHUNKSIZE (64*1024)
=20
=20
-/* A structure to summarise CFI summary info. It defines an address
- range, and for that address range, gives info on how the
- procedure's return address is to be derived from the current stack
- pointer value in that range. For example, if .raoffset is 16, then
- the return address is found in memory at (SP+16). */
+/* A structure to summarise CFI summary info for the code address
+ range [base .. base+len-1]. In short, if you know (sp,fp,ip) at
+ some point and ip is in the range [base .. base+len-1], it tells
+ you how to calculate (sp,fp) for the caller of the current
+ frame and also ra, the return address of the current frame.
+
+ First off, calculate CFA, the Canonical Frame Address, thusly:
+
+ cfa =3D if cfa_sprel then sp+cfa_off else fp+cfa_off
+
+ Once that is done, the previous frame's sp/fp values and this
+ frame's ra value can be calculated like this:
+
+ old_sp/fp/ra
+ =3D case sp/fp/ra_how of
+ CFIR_UNKNOWN -> we don't know, sorry
+ CFIR_SAME -> same as it was before (sp/fp only)
+ CFIR_CFAREL -> cfa + sp/fp/ra_off
+ CFIR_MEMCFAREL -> *( cfa + sp/fp/ra_off )
+*/
+
+#define CFIR_UNKNOWN ((UChar)0)
+#define CFIR_SAME ((UChar)1)
+#define CFIR_CFAREL ((UChar)2)
+#define CFIR_MEMCFAREL ((UChar)3)
+
typedef
struct {
- Addr base;
- UInt len;
- Int raoffset;
+ Addr base;
+ UInt len;
+ Bool cfa_sprel;
+ UChar ra_how; /* a CFIR_ value */
+ UChar sp_how; /* a CFIR_ value */
+ UChar fp_how; /* a CFIR_ value */
+ Int cfa_off;
+ Int ra_off;
+ Int sp_off;
+ Int fp_off;
}
CfiSI;
=20
+extern void VG_(ppCfiSI) ( CfiSI* );
=20
+
/* A structure which contains information pertaining to one mapped
text segment. (typedef in tool.h) */
struct _SegInfo {
@@ -196,6 +226,7 @@
Char *VG_(addStr) ( SegInfo* si, Char* str, Int len );
void VG_(addScopeInfo) ( SegInfo* si, Addr this, Addr next, Scope *scope=
);
void VG_(addLineInfo) ( SegInfo* si, Char* filename, Addr this, Addr nex=
t, Int lineno, Int entry);
+void VG_(addCfiSI) ( SegInfo* si, CfiSI* cfisi );
=20
/* Non-fatal -- use vg_panic if terminal. */
void VG_(symerr) ( Char* msg );
|