summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mwielaard@redhat.com>2008-09-10 13:51:30 +0200
committerMark Wielaard <mjw@redhat.com>2008-09-10 14:01:32 +0200
commit6b2fda5424fb9aaeabe5056fc1e7286f6c8a034a (patch)
tree8dc8f120ebb03863298f8321e62b2251962c6ee7
parentf6f5a33817ac1d406c8c2687e32493cbc38ef4e7 (diff)
downloadsystemtap-steved-6b2fda5424fb9aaeabe5056fc1e7286f6c8a034a.tar.gz
systemtap-steved-6b2fda5424fb9aaeabe5056fc1e7286f6c8a034a.tar.xz
systemtap-steved-6b2fda5424fb9aaeabe5056fc1e7286f6c8a034a.zip
Record module base and use it for adjusting start locations in dwarf unwinder.
-rw-r--r--ChangeLog4
-rw-r--r--runtime/ChangeLog7
-rw-r--r--runtime/sym.h2
-rw-r--r--runtime/unwind.c27
-rw-r--r--translate.cxx1
5 files changed, 38 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index c122f409..8ce62fb6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2008-09-10 Mark Wielaard <mjw@redhat.com>
+ * translate.cxx (dump_unwindsyms): Output module_base.
+
+2008-09-10 Mark Wielaard <mjw@redhat.com>
+
* translate.cxx (get_unwind_data): New function.
(dump_unwindsyms): Output unwind data.
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 7502bf34..d794b4a1 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,5 +1,12 @@
2008-09-10 Mark Wielaard <mjw@redhat.com>
+ * sym.h (_stp_module): Add module_base field.
+ * unwind.c (adjustStartLoc): New function.
+ (_stp_search_unwind_hdr): Use adjustStartLoc.
+ (unwind): Likewise.
+
+2008-09-10 Mark Wielaard <mjw@redhat.com>
+
* unwind.c (unwind): Use _stp_mod_sec_lookup to get module and
unwind tables.
* runtime.h (STP_USE_FRAME_BUFFER): Disable by default for now.
diff --git a/runtime/sym.h b/runtime/sym.h
index b2fb8ee9..564f4eb2 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -34,6 +34,8 @@ struct _stp_module {
/* is unloading. */
unsigned long module; /* XXX: why not struct module * ? */
+ unsigned long module_base;
+
/* the stack unwind data for this module */
void *unwind_data;
void *unwind_hdr;
diff --git a/runtime/unwind.c b/runtime/unwind.c
index 7b19573d..db8ae664 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -550,10 +550,27 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, s
return result && ptr.p8 == end && (targetLoc == 0 || state->label == NULL);
}
+// This is an address inside a module, adjust.
+static unsigned long
+adjustStartLoc (unsigned long startLoc,
+ struct _stp_module *m,
+ struct _stp_section *s)
+{
+ if (startLoc && (strcmp (m->name, "kernel") != 0))
+ {
+ startLoc = _stp_module_relocate (m->name, s->name,
+ startLoc);
+ startLoc -= m->module_base;
+ }
+ return startLoc;
+}
+
/* If we previously created an unwind header, then use it now to binary search */
/* for the FDE corresponding to pc. */
-static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m)
+static u32 *_stp_search_unwind_hdr(unsigned long pc,
+ struct _stp_module *m,
+ struct _stp_section *s)
{
const u8 *ptr, *end, *hdr = m->unwind_hdr;
unsigned long startLoc;
@@ -600,6 +617,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m)
do {
const u8 *cur = ptr + (num / 2) * (2 * tableSize);
startLoc = read_pointer(&cur, cur + tableSize, hdr[3]);
+ startLoc = adjustStartLoc(startLoc, m, s);
if (pc < startLoc)
num /= 2;
else {
@@ -608,7 +626,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m)
}
} while (startLoc && num > 1);
- if (num == 1 && (startLoc = read_pointer(&ptr, ptr + tableSize, hdr[3])) != 0 && pc >= startLoc)
+ if (num == 1 && (startLoc = adjustStartLoc(read_pointer(&ptr, ptr + tableSize, hdr[3]), m, s)) != 0 && pc >= startLoc)
fde = (void *)read_pointer(&ptr, ptr + tableSize, hdr[3]);
dbug_unwind(1, "returning fde=%lx startLoc=%lx", fde, startLoc);
@@ -695,7 +713,7 @@ int unwind(struct unwind_frame_info *frame)
goto err;
}
- fde = _stp_search_unwind_hdr(pc, m);
+ fde = _stp_search_unwind_hdr(pc, m, s);
dbug_unwind(1, "%s: fde=%lx\n", m->name, fde);
/* found the fde, now set startLoc and endLoc */
@@ -705,6 +723,8 @@ int unwind(struct unwind_frame_info *frame)
ptr = (const u8 *)(fde + 2);
ptrType = fde_pointer_type(cie);
startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType);
+ startLoc = adjustStartLoc(startLoc, m, s);
+
dbug_unwind(2, "startLoc=%lx, ptrType=%s", startLoc, _stp_eh_enc_name(ptrType));
if (!(ptrType & DW_EH_PE_indirect))
ptrType &= DW_EH_PE_FORM | DW_EH_PE_signed;
@@ -734,6 +754,7 @@ int unwind(struct unwind_frame_info *frame)
ptr = (const u8 *)(fde + 2);
startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType);
+ startLoc = adjustStartLoc(startLoc, m, s);
dbug_unwind(2, "startLoc=%lx, ptrType=%s", startLoc, _stp_eh_enc_name(ptrType));
if (!startLoc)
continue;
diff --git a/translate.cxx b/translate.cxx
index d4507a1f..7c1469df 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4551,6 +4551,7 @@ dump_unwindsyms (Dwfl_Module *m,
c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl;
c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl;
+ c->output << ".module_base = 0x" << hex << base << dec << ", " << endl;
if (unwind != NULL)
{