summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog38
-rw-r--r--runtime/runtime.h8
-rw-r--r--runtime/stack-i386.c6
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/sym.c55
-rw-r--r--runtime/sym.h7
-rw-r--r--runtime/unwind.c32
7 files changed, 115 insertions, 33 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index f7a844d8..97b1a0c0 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,36 @@
+2008-09-10 Frank Ch. Eigler <fche@elastic.org>
+
+ * runtime.h (STP_USE_FRAME_POINTER): Remove architecture #if's.
+ All will activate it if CONFIG_FRAME_POINTER unless
+ STP_USE_DWARF_UNWINDER.
+ * stack-i386.c: (__stp_stack_print): Handle !DWARF and !FRAME
+ configuration.
+
+2008-09-10 Mark Wielaard <mjw@redhat.com>
+
+ * sym.h (_stp_module): Rename module_base to dwarf_module_base.
+ * unwind.c (adjustStartLoc): Document and use dwarf_module_base.
+
+2008-09-10 Mark Wielaard <mjw@redhat.com>
+
+ * runtime.h (CONFIG_FRAME_POINTER): Don't enable when
+ STP_USE_DWARF_UNWINDER is already defined.
+
+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.
+ * stack-x86_64.c (__stp_stack_print): Add levels to
+ _stp_stack_print_fallback call.
+
2008-09-09 Masami Hiramatsu <mhiramat@redhat.com>
* regs-ia64.c (__ia64_fetch_register): Return the address of the
@@ -15,6 +48,11 @@
2008-09-09 Mark Wielaard <mwielaard@redhat.com>
+ * sym.c (_stp_mod_sec_lookup): New function, extracted from
+ _stp_kallsyms_lookup.
+
+2008-09-09 Mark Wielaard <mwielaard@redhat.com>
+
* sym.c (_stp_kallsyms_lookup): Correct this_section_offset
calculation.
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fd0cac9e..cd3d0b11 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -68,13 +68,15 @@ static struct
#ifdef CONFIG_FRAME_POINTER
/* Just because frame pointers are available does not mean we can trust them. */
-#if defined (__i386__) || defined (__arm__)
+#ifndef STP_USE_DWARF_UNWINDER
#define STP_USE_FRAME_POINTER
#endif
#endif
-/* dwarf unwinder only tested so far on i386 and x86_64 */
-#if !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__))
+/* dwarf unwinder only tested so far on i386 and x86_64,
+ but globally disabled for now */
+#if 0
+// !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__))
#define STP_USE_DWARF_UNWINDER
#endif
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index ad101889..ed7e2ce1 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -54,9 +54,10 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
fp = next_fp;
}
#else
+#ifdef STP_USE_DWARF_UNWINDER
struct unwind_frame_info info;
arch_unw_init_frame_info(&info, regs);
-
+
while (levels && !arch_unw_user_mode(&info)) {
int ret = unwind(&info);
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
@@ -71,5 +72,8 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
_stp_stack_print_fallback(context, UNW_SP(&info), verbose, levels);
break;
}
+#else /* ! STP_USE_DWARF_UNWINDER */
+ _stp_stack_print_fallback(context, (unsigned long)&REG_SP(regs), verbose, levels);
#endif /* STP_USE_FRAME_POINTER */
+#endif
}
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 783e72bd..d3ec91cf 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -45,6 +45,6 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels)
break;
}
#else /* ! STP_USE_DWARF_UNWINDER */
- _stp_stack_print_fallback(REG_SP(regs), verbose);
+ _stp_stack_print_fallback(REG_SP(regs), verbose, levels);
#endif
}
diff --git a/runtime/sym.c b/runtime/sym.c
index b594d9c2..1a9e26b2 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -73,6 +73,37 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi
}
+/* Return module owner and fills in closest section of the address
+ if found, return NULL otherwise.
+ XXX: needs to be address-space-specific. */
+static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
+ struct _stp_section **sec)
+{
+ struct _stp_module *m = NULL;
+ unsigned midx = 0;
+ unsigned long closest_section_offset = ~0;
+ for (midx = 0; midx < _stp_num_modules; midx++)
+ {
+ unsigned secidx;
+ for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++)
+ {
+ unsigned long this_section_addr;
+ unsigned long this_section_offset;
+ this_section_addr = _stp_modules[midx]->sections[secidx].addr;
+ if (addr < this_section_addr) continue;
+ this_section_offset = addr - this_section_addr;
+ if (this_section_offset < closest_section_offset)
+ {
+ closest_section_offset = this_section_offset;
+ m = _stp_modules[midx];
+ *sec = & m->sections[secidx];
+ }
+ }
+ }
+ return m;
+}
+
+
/* XXX: needs to be address-space-specific. */
static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbolsize,
unsigned long *offset,
@@ -86,29 +117,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
unsigned long flags;
unsigned end, begin = 0;
- /* Find the closest section (and its owner module); fill in m & sec. */
- {
- unsigned midx = 0;
- unsigned long closest_section_offset = ~0;
- for (midx = 0; midx < _stp_num_modules; midx++)
- {
- unsigned secidx;
- for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++)
- {
- unsigned long this_section_addr = _stp_modules[midx]->sections[secidx].addr;
- unsigned long this_section_offset;
- if (addr < this_section_addr) continue;
- this_section_offset = addr - this_section_addr;
- if (this_section_offset < closest_section_offset)
- {
- closest_section_offset = this_section_offset;
- m = _stp_modules[midx];
- sec = & m->sections[secidx];
- }
- }
- }
- }
-
+ m = _stp_mod_sec_lookup(addr, &sec);
if (unlikely (m == NULL || sec == NULL))
return NULL;
diff --git a/runtime/sym.h b/runtime/sym.h
index b2fb8ee9..5888d2c7 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -33,7 +33,12 @@ struct _stp_module {
/* any notifier hooks that will tell us when a module */
/* is unloading. */
unsigned long module; /* XXX: why not struct module * ? */
-
+
+ /* This is to undo .debug_frame relocation performed by elfutils, */
+ /* which is done during the translate phase when we encode the */
+ /* unwind data into the module. See adjustStartLoc() in unwind.c. */
+ unsigned long dwarf_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 21ea4559..bc8a93dc 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -550,10 +550,29 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, s
return result && ptr.p8 == end && (targetLoc == 0 || state->label == NULL);
}
+// If this is an address inside a module, adjust for section relocation
+// and the elfutils base relocation done during loading of the .dwarf_frame
+// in translate.cxx.
+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->dwarf_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 +619,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 +628,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);
@@ -676,6 +696,7 @@ int unwind(struct unwind_frame_info *frame)
signed ptrType = -1;
uleb128_t retAddrReg = 0;
struct _stp_module *m;
+ struct _stp_section *s = NULL;
struct unwind_state state;
dbug_unwind(1, "pc=%lx, %lx", pc, UNW_PC(frame));
@@ -683,7 +704,7 @@ int unwind(struct unwind_frame_info *frame)
if (UNW_PC(frame) == 0)
return -EINVAL;
- m = NULL /*_stp_get_unwind_info(pc) */;
+ m = _stp_mod_sec_lookup (pc, &s);
if (unlikely(m == NULL)) {
dbug_unwind(1, "No module found for pc=%lx", pc);
return -EINVAL;
@@ -694,7 +715,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 */
@@ -704,6 +725,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;
@@ -733,6 +756,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;