summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2008-09-10 12:24:44 -0400
committerDave Brolley <brolley@redhat.com>2008-09-10 12:24:44 -0400
commit4efa91dd26956c961b2999470ced965a448ed31b (patch)
treeb27b7b323eefbe3303e630809776b626987aa421 /runtime
parentbb997bd81d90b94e734c8c93402353eddd0bc408 (diff)
parent675fb1ddeec8cd22e17ab989f8a813a375ae6226 (diff)
downloadsystemtap-steved-4efa91dd26956c961b2999470ced965a448ed31b.tar.gz
systemtap-steved-4efa91dd26956c961b2999470ced965a448ed31b.tar.xz
systemtap-steved-4efa91dd26956c961b2999470ced965a448ed31b.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog45
-rw-r--r--runtime/regs-ia64.c21
-rw-r--r--runtime/runtime.h8
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/sym.c55
-rw-r--r--runtime/sym.h7
-rw-r--r--runtime/syscall.h42
-rw-r--r--runtime/task_finder.c6
-rw-r--r--runtime/unwind.c32
9 files changed, 180 insertions, 38 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 71cd97e4..2438ee5e 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,48 @@
+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
+ register.
+ (ia64_fetch_register): Use __ia64_fetch_register.
+ * syscall.h (____stp_user_syscall_arg): Use __ia64_fetch_register.
+ (__stp_user_syscall_arg): Wrapping ____stp_user_syscall_arg to pass the
+ unwind address cache.
+ * task_finder.c (__stp_utrace_task_finder_target_syscall_): Added dummy
+ unwind address cache.
+
+2008-09-09 Masami Hiramatsu <mhiramat@redhat.com>
+
+ * syscall.h: Added ia64 support.
+
+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
diff --git a/runtime/regs-ia64.c b/runtime/regs-ia64.c
index fd8d8ca8..8ce3e4c3 100644
--- a/runtime/regs-ia64.c
+++ b/runtime/regs-ia64.c
@@ -61,27 +61,36 @@ static void ia64_stap_get_arbsp(struct unw_frame_info *info, void *arg)
-(__offset + (regs->cr_ifs & 127)));\
}
-static long ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
+static long *
+__ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
{
struct ia64_stap_get_arbsp_param pa;
if (regno == 12)
- return pt_regs->r12;
+ return &pt_regs->r12;
if (regno >= 8 && regno <= 11)
- return *(unsigned long *)(&pt_regs->r8 + regno - 8);
+ return (long *)(&pt_regs->r8 + regno - 8);
else if (regno < 32 || regno > 127)
- return 0;
+ return NULL;
if (!*cache) {
pa.ip = pt_regs->cr_iip;
unw_init_running(ia64_stap_get_arbsp, &pa);
if (pa.address == 0)
- return 0;
+ return NULL;
*cache = pa.address;
}
- return *ia64_rse_skip_regs(*cache, regno-32);
+ return ia64_rse_skip_regs(*cache, regno-32);
+}
+
+static long
+ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
+{
+ long *reg;
+ reg = __ia64_fetch_register(regno, pt_regs, cache);
+ return (reg != NULL)? *reg : 0;
}
static void ia64_store_register(int regno,
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fd0cac9e..db793aa5 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -68,13 +68,17 @@ static struct
#ifdef CONFIG_FRAME_POINTER
/* Just because frame pointers are available does not mean we can trust them. */
+#ifndef STP_USE_DWARF_UNWINDER
#if defined (__i386__) || defined (__arm__)
#define STP_USE_FRAME_POINTER
#endif
#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-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/syscall.h b/runtime/syscall.h
index 24e93463..24fc7b1c 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -66,7 +66,15 @@
#define MUNMAP_SYSCALL_NO(tsk) 91
#define MREMAP_SYSCALL_NO(tsk) 163
#endif
-
+
+#if defined(__ia64__)
+#define MMAP_SYSCALL_NO(tsk) 1151
+#define MMAP2_SYSCALL_NO(tsk) 1172
+#define MPROTECT_SYSCALL_NO(tsk) 1155
+#define MUNMAP_SYSCALL_NO(tsk) 1152
+#define MREMAP_SYSCALL_NO(tsk) 1156
+#endif
+
#if !defined(MMAP_SYSCALL_NO) || !defined(MMAP2_SYSCALL_NO) \
|| !defined(MPROTECT_SYSCALL_NO) || !defined(MUNMAP_SYSCALL_NO) \
|| !defined(MREMAP_SYSCALL_NO)
@@ -95,6 +103,14 @@ __stp_user_syscall_nr(struct pt_regs *regs)
}
#endif
+#if defined(__ia64__)
+static inline unsigned long
+__stp_user_syscall_nr(struct pt_regs *regs)
+{
+ return regs->r15;
+}
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
static inline long *
__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
@@ -129,6 +145,14 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
}
#endif
+#if defined(__ia64__)
+static inline long *
+__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+ return &regs->r8;
+}
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
static inline long *
__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
@@ -211,4 +235,20 @@ __stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
}
#endif
+#if defined(__ia64__)
+#define __stp_user_syscall_arg(task, regs, n) \
+ ____stp_user_syscall_arg(task, regs, n, &c->unwaddr)
+
+static inline long *
+____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
+ unsigned int n, unsigned long **cache)
+{
+ if (n > 5) {
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+ return __ia64_fetch_register(n + 32, regs, cache);
+}
+#endif
+
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 2d4eed15..cbb10d35 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -843,6 +843,9 @@ __stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
struct vm_area_struct *vma;
unsigned long *arg0_addr, arg0;
int rc;
+#if defined(__ia64__)
+ struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
+#endif
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
debug_task_finder_detach();
@@ -950,6 +953,9 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
struct mm_struct *mm;
struct vm_area_struct *vma;
struct __stp_tf_vma_entry *entry = NULL;
+#if defined(__ia64__)
+ struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
+#endif
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
debug_task_finder_detach();
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;