summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-12-21 13:02:19 +0100
committerMark Wielaard <mjw@redhat.com>2009-12-21 13:24:36 +0100
commitea549ffc2915aa58861637472b12196222673fa2 (patch)
tree5bf80c4245ddfd3c12af6f7ee2c4b75075efe86b /runtime
parent0c487e433fd6343e49b1e9dbc6492f38cfe26143 (diff)
downloadsystemtap-steved-ea549ffc2915aa58861637472b12196222673fa2.tar.gz
systemtap-steved-ea549ffc2915aa58861637472b12196222673fa2.tar.xz
systemtap-steved-ea549ffc2915aa58861637472b12196222673fa2.zip
PR11015 Support shared library reloading (in different processes)
* runtime/task_finder_vma.c (stap_remove_vma_map_info): Return negative status on failure. (stap_find_vma_map_info): Likewise. (stap_find_vma_map_info_user): New function. (stap_drop_vma_maps): New function. * runtime/sym.h (addr): Renamed to static_addr, to store addresses for sections which are always mapped at the same address. (_stp_module_relocate): Add extra struct task_struct *tsk argument. * runtime/sym.c (_stp_tf_exec_cb): New callback, calls stap_drop_vma_maps. (_stp_tf_mmap_cb): Don't store address in module.section, but call stap_add_vma_map_info() per tsk->group_leader for matched module. Don't register empty/null modules. (_stp_module_relocate): Take extra struct task_struct *tsk argument, cache last tsk used. Only use section->static_addr for none dynamic modules. Use stap_find_vma_map_info_user() to locate dynamic modules. (_stp_mod_sec_lookup): Add extra argument unsigned long *rel_addr to optionally store relative address when module/section found. (_stp_kallsyms_lookup): Use _stp_mod_sec_lookup to find relative address. (_stp_sym_init): Register _stp_tf_exec_cb in stap_task_finder_target. Add error check to see if task finder could be initialized. * dwflpp.cxx (emit_address): Pass NULL for kernel/modules and current for user tasks to _stp_module_relocate. * runtime/transport/symbols.c (_stp_do_relocation): Set new static_addr _stp_section field. * runtime/unwind.c (adjustStartLoc): Take new struct task_struct *tsk argument and pass to stap_find_vma_map_info_user and _stp_module_relocate to find adjusted addr. (_stp_search_unwind_hdr): Pass through struct task_struct *tsk. (unwind_frame): Likewise. * tapset/context-symbols.stp (probemod): Add NULL to _stp_mod_sec_lookup call to indicate we aren't interested in relative address. * tapsets.cxx (dwarf_derived_probe_group::emit_module_init): Pass NULL to _stp_module_relocate to indicate kernel/module address.
Diffstat (limited to 'runtime')
-rw-r--r--runtime/sym.c167
-rw-r--r--runtime/sym.h7
-rw-r--r--runtime/task_finder_vma.c71
-rw-r--r--runtime/transport/symbols.c2
-rw-r--r--runtime/unwind.c31
5 files changed, 201 insertions, 77 deletions
diff --git a/runtime/sym.c b/runtime/sym.c
index cd0c8a71..06691dc9 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -19,6 +19,22 @@
/* Callback that needs to be registered (in
session.unwindsyms_modules) for every user task path for which we
might need symbols or unwind info. */
+static int _stp_tf_exec_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ int register_p,
+ int process_p)
+{
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "tsk %d:%d , register_p: %d, process_p: %d\n",
+ tsk->pid, tsk->tgid, register_p, process_p);
+#endif
+ if (process_p && ! register_p)
+ stap_drop_vma_maps(tsk);
+
+ return 0;
+}
+
static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
struct task_struct *tsk,
char *path,
@@ -42,40 +58,22 @@ static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
if (strcmp(path, _stp_modules[i]->path) == 0)
{
#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "vm_cb: matched path %s to module\n",
- path);
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "vm_cb: matched path %s to module (for sec: %s)\n",
+ path, _stp_modules[i]->sections[0].name);
#endif
- module = _stp_modules[i];
- // cheat...
- // We are abusing the "first" section address
- // here to indicate where the module (actually
- // first segment) is loaded (which is why we
- // are ignoring the offset). It would be good
- // to redesign the stp_module/stp_section
- // data structures to better align with the
- // actual memory mappings we are interested
- // in (especially the "section" naming is
- // slightly confusing since what we really
- // seem to mean are elf segments (which can
- // contain multiple elf sections). PR11015.
- if (strcmp(".dynamic",
- module->sections[0].name) == 0)
- {
- if (module->sections[0].addr == 0)
- module->sections[0].addr = addr;
- else if (module->sections[0].addr != addr)
- _stp_error ("Reloaded module '%s'"
- " at 0x%lx, was 0x%lx\n",
- path, addr,
- module->sections[0].addr);
- }
- break;
+ module = _stp_modules[i];
+ /* XXX We really only need to register .dynamic
+ sections, but .absolute exes are also necessary
+ atm. */
+ return stap_add_vma_map_info(tsk->group_leader,
+ addr,
+ addr + length,
+ offset,
+ module);
}
}
}
- stap_add_vma_map_info(tsk->group_leader, addr, addr + length, offset,
- module);
return 0;
}
@@ -84,15 +82,25 @@ static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt,
unsigned long addr,
unsigned long length)
{
+ /* Unconditionally remove vm map info, ignore if not present. */
stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0);
return 0;
}
-/* XXX: this needs to be address-space-specific. */
-static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset)
+/* Returns absolute address of offset into module/section for given task.
+ If tsk == NULL module/section is assumed to be absolute/static already
+ (e.g. kernel, kernel-modules and static executables). Returns zero when
+ module and section couldn't be found (aren't in memory yet). */
+static unsigned long _stp_module_relocate(const char *module,
+ const char *section,
+ unsigned long offset,
+ struct task_struct *tsk)
{
+ /* XXX This doesn't look thread safe XXX */
static struct _stp_module *last = NULL;
static struct _stp_section *last_sec;
+ static struct task_struct *last_tsk;
+ static unsigned long last_offset;
unsigned i, j;
/* if module is -1, we invalidate last. _stp_del_module calls this when modules are deleted. */
@@ -110,8 +118,10 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
/* Most likely our relocation is in the same section of the same module as the last. */
if (last) {
- if (!strcmp(module, last->name) && !strcmp(section, last_sec->name)) {
- offset += last_sec->addr;
+ if (!strcmp(module, last->name)
+ && !strcmp(section, last_sec->name)
+ && tsk == last_tsk) {
+ offset += last_offset;
dbug_sym(1, "cached address=%lx\n", offset);
return offset;
}
@@ -124,11 +134,33 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
for (j = 0; j < last->num_sections; j++) {
last_sec = &last->sections[j];
if (!strcmp(section, last_sec->name)) {
-
- if (last_sec->addr == 0) /* module/section not in memory */
- continue;
-
- offset += last_sec->addr;
+ /* mod and sec name match. tsk should match dynamic/static. */
+ if (last_sec->static_addr != 0) {
+ last_offset = last_sec->static_addr;
+ } else {
+ if (!tsk) { /* static section, not in memory yet? */
+ if (strcmp(".dynamic", section) == 0)
+ _stp_error("internal error, _stp_module_relocate '%s' "
+ "section '%s', should not be tsk dynamic\n",
+ module, section);
+ last = NULL;
+ return 0;
+ } else { /* dynamic section, look up through tsk vma. */
+ if (strcmp(".dynamic", last_sec->name) != 0) {
+ _stp_error("internal error, _stp_module_relocate '%s' "
+ "section '%s', should not be tsk dynamic\n",
+ module, section);
+ return 0;
+ }
+ if (stap_find_vma_map_info_user(tsk->group_leader, last,
+ &last_offset, NULL,
+ NULL) != 0) {
+ last = NULL;
+ return 0;
+ }
+ }
+ }
+ offset += last_offset;
dbug_sym(1, "address=%lx\n", offset);
return offset;
}
@@ -140,11 +172,12 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
}
/* Return module owner and, if sec != NULL, fills in closest section
- of the address if found, return NULL otherwise.
- XXX: needs to be address-space-specific. */
+ of the address if found, return NULL otherwise. Fills in rel_addr
+ (addr relative to closest section) when given. */
static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
struct task_struct *task,
- struct _stp_section **sec)
+ struct _stp_section **sec,
+ unsigned long *rel_addr)
{
void *user = NULL;
unsigned midx = 0;
@@ -160,11 +193,21 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
{
struct _stp_module *m = (struct _stp_module *)user;
if (sec)
- *sec = &m->sections[0]; // XXX check actual section and relocate
+ *sec = &m->sections[0]; // dynamic user modules have one section.
+ if (rel_addr)
+ {
+ /* XXX .absolute sections really shouldn't be here... */
+ if (strcmp(".dynamic", m->sections[0].name) == 0)
+ *rel_addr = addr - vm_start;
+ else
+ *rel_addr = addr;
+ }
dbug_sym(1, "found section %s in module %s at 0x%lx\n",
m->sections[0].name, m->name, vm_start);
return m;
}
+ /* XXX should really not fallthrough, but sometimes current is passed
+ when it shouldn't - see probefunc() for example. */
}
for (midx = 0; midx < _stp_num_modules; midx++)
@@ -174,12 +217,14 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
{
unsigned long sec_addr;
unsigned long sec_size;
- sec_addr = _stp_modules[midx]->sections[secidx].addr;
+ sec_addr = _stp_modules[midx]->sections[secidx].static_addr;
sec_size = _stp_modules[midx]->sections[secidx].size;
if (addr >= sec_addr && addr < sec_addr + sec_size)
{
if (sec)
*sec = & _stp_modules[midx]->sections[secidx];
+ if (rel_addr)
+ *rel_addr = addr - sec_addr;
return _stp_modules[midx];
}
}
@@ -188,7 +233,6 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
}
-/* XXX: needs to be address-space-specific. */
static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbolsize,
unsigned long *offset,
const char **modname,
@@ -200,13 +244,14 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
struct _stp_section *sec = NULL;
struct _stp_symbol *s = NULL;
unsigned end, begin = 0;
+ unsigned long rel_addr = 0;
- m = _stp_mod_sec_lookup(addr, task, &sec);
+ m = _stp_mod_sec_lookup(addr, task, &sec, &rel_addr);
if (unlikely (m == NULL || sec == NULL))
return NULL;
/* NB: relativize the address to the section. */
- addr -= sec->addr;
+ addr = rel_addr;
end = sec->num_symbols;
/* binary search for symbols within the module */
@@ -268,9 +313,9 @@ static int _stp_module_check(void)
/* notes end address */
if (!strcmp(m->name, "kernel")) {
notes_addr = _stp_module_relocate("kernel",
- "_stext", m->build_id_offset);
+ "_stext", m->build_id_offset, NULL);
base_addr = _stp_module_relocate("kernel",
- "_stext", 0);
+ "_stext", 0, NULL);
} else {
notes_addr = m->notes_sect + m->build_id_offset;
base_addr = m->notes_sect;
@@ -446,14 +491,20 @@ static void _stp_sym_init(void)
static struct stap_task_finder_target vmcb = {
// NB: no .pid, no .procname filters here.
// This means that we get a system-wide mmap monitoring
- // widget while the script is running. (The system-wideness may
- // be restricted by stap -c or -x.) But this seems to
- // be necessary if we want to to stack tracebacks through arbitrary
- // shared libraries. XXX: There may be an optimization opportunity
- // for executables (for which the main task-finder callback should be
- // sufficient).
+ // widget while the script is running. (The
+ // system-wideness may be restricted by stap -c or
+ // -x.) But this seems to be necessary if we want to
+ // to stack tracebacks through arbitrary shared libraries.
+ //
+ // XXX: There may be an optimization opportunity
+ // for executables (for which the main task-finder
+ // callback should be sufficient).
+ .pid = 0,
+ .procname = NULL,
+ .callback = &_stp_tf_exec_cb,
.mmap_callback = &_stp_tf_mmap_cb,
.munmap_callback = &_stp_tf_munmap_cb,
+ .mprotect_callback = NULL
};
if (! initialized) {
int rc;
@@ -462,8 +513,10 @@ static void _stp_sym_init(void)
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__, "registered vmcb");
#endif
- (void) rc; // XXX
- initialized = 1;
+ if (rc != 0)
+ _stp_error("Couldn't register task finder target: %d\n", rc);
+ else
+ initialized = 1;
}
#endif
}
diff --git a/runtime/sym.h b/runtime/sym.h
index 9f2bdfd0..ce6ab736 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -17,7 +17,7 @@ struct _stp_symbol {
struct _stp_section {
const char *name;
- unsigned long addr; /* XXX: belongs in per-address-space tables */
+ unsigned long static_addr; /* XXX non-null if everywhere the same. */
unsigned long size; /* length of the address space module covers. */
struct _stp_symbol *symbols; /* ordered by address */
unsigned num_symbols;
@@ -70,7 +70,10 @@ static unsigned long _stp_kretprobe_trampoline;
_stp_sym_init () should track vma maps. */
static char _stp_need_vma_tracker;
-static unsigned long _stp_module_relocate (const char *module, const char *section, unsigned long offset);
+static unsigned long _stp_module_relocate (const char *module,
+ const char *section,
+ unsigned long offset,
+ struct task_struct *tsk);
static struct _stp_module *_stp_get_unwind_info (unsigned long addr);
#endif /* _STP_SYM_H_ */
diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
index ed9c6f4f..9a32323f 100644
--- a/runtime/task_finder_vma.c
+++ b/runtime/task_finder_vma.c
@@ -270,6 +270,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
// Remove the vma entry from the vma hash table.
+// Returns -ESRCH if the entry isn't present.
static int
stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
unsigned long vm_end, unsigned long vm_pgoff)
@@ -277,6 +278,7 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
struct hlist_head *head;
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
+ int rc = -ESRCH;
// Take a write lock since we are most likely going to delete
// after reading.
@@ -286,13 +288,15 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
if (entry != NULL) {
hlist_del(&entry->hlist);
__stp_tf_vma_put_free_entry(entry);
+ rc = 0;
}
write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
- return 0;
+ return rc;
}
-// Finds vma info if the vma is present in the vma map hash table.
-// Returns ESRCH if not present. The __stp_tf_vma_lock must *not* be
+// Finds vma info if the vma is present in the vma map hash table for
+// a given task and address (between vm_start and vm_end).
+// Returns -ESRCH if not present. The __stp_tf_vma_lock must *not* be
// locked before calling this function.
static int
stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
@@ -303,7 +307,7 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
struct __stp_tf_vma_entry *found_entry = NULL;
- int rc = ESRCH;
+ int rc = -ESRCH;
unsigned long flags;
read_lock_irqsave(&__stp_tf_vma_lock, flags);
@@ -330,3 +334,62 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return rc;
}
+
+// Finds vma info if the vma is present in the vma map hash table for
+// a given task with the given user handle.
+// Returns -ESRCH if not present. The __stp_tf_vma_lock must *not* be
+// locked before calling this function.
+static int
+stap_find_vma_map_info_user(struct task_struct *tsk, void *user,
+ unsigned long *vm_start, unsigned long *vm_end,
+ unsigned long *vm_pgoff)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct __stp_tf_vma_entry *entry;
+ struct __stp_tf_vma_entry *found_entry = NULL;
+ int rc = -ESRCH;
+
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_vma_lock, flags);
+ head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (tsk->pid == entry->pid
+ && user == entry->user) {
+ found_entry = entry;
+ break;
+ }
+ }
+ if (found_entry != NULL) {
+ if (vm_start != NULL)
+ *vm_start = found_entry->vm_start;
+ if (vm_end != NULL)
+ *vm_end = found_entry->vm_end;
+ if (vm_pgoff != NULL)
+ *vm_pgoff = found_entry->vm_pgoff;
+ rc = 0;
+ }
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
+ return rc;
+}
+
+static int
+stap_drop_vma_maps(struct task_struct *tsk)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct hlist_node *n;
+ struct __stp_tf_vma_entry *entry;
+
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
+ head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
+ hlist_for_each_entry_safe(entry, node, n, head, hlist) {
+ if (tsk->pid == entry->pid) {
+ hlist_del(&entry->hlist);
+ __stp_tf_vma_put_free_entry(entry);
+ }
+ }
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
+ return 0;
+}
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index a214d1f2..e2f9fd65 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -61,7 +61,7 @@ static void _stp_do_relocation(const char __user *buf, size_t count)
continue;
else
{
- _stp_modules[mi]->sections[si].addr = msg.address;
+ _stp_modules[mi]->sections[si].static_addr = msg.address;
break;
}
} /* loop over sections */
diff --git a/runtime/unwind.c b/runtime/unwind.c
index 7607770e..c8e3580d 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -496,7 +496,7 @@ static char *_stp_eh_enc_name(signed type)
// and the elfutils base relocation done during loading of the .dwarf_frame
// in translate.cxx.
static unsigned long
-adjustStartLoc (unsigned long startLoc,
+adjustStartLoc (unsigned long startLoc, struct task_struct *tsk,
struct _stp_module *m,
struct _stp_section *s,
unsigned ptrType, int is_ehframe)
@@ -521,10 +521,14 @@ adjustStartLoc (unsigned long startLoc,
return startLoc;
}
- if (strcmp (s->name, ".dynamic") == 0)
- return startLoc + s->addr;
+ if (strcmp (s->name, ".dynamic") == 0) {
+ unsigned long vm_addr;
+ if (stap_find_vma_map_info_user(tsk->group_leader, m,
+ &vm_addr, NULL, NULL) == 0)
+ return startLoc + vm_addr;
+ }
- startLoc = _stp_module_relocate (m->name, s->name, startLoc);
+ startLoc = _stp_module_relocate (m->name, s->name, startLoc, tsk);
startLoc -= m->dwarf_module_base;
return startLoc;
}
@@ -532,7 +536,7 @@ adjustStartLoc (unsigned long startLoc,
/* If we previously created an unwind header, then use it now to binary search */
/* for the FDE corresponding to pc. XXX FIXME not currently supported. */
-static u32 *_stp_search_unwind_hdr(unsigned long pc,
+static u32 *_stp_search_unwind_hdr(unsigned long pc, struct task_struct *tsk,
struct _stp_module *m,
struct _stp_section *s)
{
@@ -581,7 +585,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc,
do {
const u8 *cur = ptr + (num / 2) * (2 * tableSize);
startLoc = read_pointer(&cur, cur + tableSize, hdr[3]);
- startLoc = adjustStartLoc(startLoc, m, s, hdr[3], 1);
+ startLoc = adjustStartLoc(startLoc, tsk, m, s, hdr[3], 1);
if (pc < startLoc)
num /= 2;
else {
@@ -590,7 +594,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc,
}
} while (startLoc && num > 1);
- if (num == 1 && (startLoc = adjustStartLoc(read_pointer(&ptr, ptr + tableSize, hdr[3]), m, s, hdr[3], 1)) != 0 && pc >= startLoc)
+ if (num == 1 && (startLoc = adjustStartLoc(read_pointer(&ptr, ptr + tableSize, hdr[3]), tsk, m, s, hdr[3], 1)) != 0 && pc >= startLoc)
fde = (void *)read_pointer(&ptr, ptr + tableSize, hdr[3]);
dbug_unwind(1, "returning fde=%lx startLoc=%lx", (unsigned long) fde, startLoc);
@@ -601,6 +605,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc,
* number in case of an error. A positive return means unwinding is finished;
* don't try to fallback to dumping addresses on the stack. */
static int unwind_frame(struct unwind_frame_info *frame,
+ struct task_struct *tsk,
struct _stp_module *m, struct _stp_section *s,
void *table, uint32_t table_len, int is_ehframe)
{
@@ -619,7 +624,7 @@ static int unwind_frame(struct unwind_frame_info *frame,
goto err;
}
- fde = _stp_search_unwind_hdr(pc, m, s);
+ fde = _stp_search_unwind_hdr(pc, tsk, m, s);
dbug_unwind(1, "%s: fde=%lx\n", m->name, (unsigned long) fde);
/* found the fde, now set startLoc and endLoc */
@@ -629,7 +634,7 @@ static int unwind_frame(struct unwind_frame_info *frame,
ptr = (const u8 *)(fde + 2);
ptrType = fde_pointer_type(cie, table, table_len);
startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType);
- startLoc = adjustStartLoc(startLoc, m, s, ptrType, is_ehframe);
+ startLoc = adjustStartLoc(startLoc, tsk, m, s, ptrType, is_ehframe);
dbug_unwind(2, "startLoc=%lx, ptrType=%s\n", startLoc, _stp_eh_enc_name(ptrType));
if (!(ptrType & DW_EH_PE_indirect))
@@ -660,7 +665,7 @@ static int unwind_frame(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, ptrType, is_ehframe);
+ startLoc = adjustStartLoc(startLoc, tsk, m, s, ptrType, is_ehframe);
dbug_unwind(2, "startLoc=%lx, ptrType=%s\n", startLoc, _stp_eh_enc_name(ptrType));
if (!startLoc)
continue;
@@ -902,18 +907,18 @@ static int unwind(struct unwind_frame_info *frame, struct task_struct *tsk)
if (UNW_PC(frame) == 0)
return -EINVAL;
- m = _stp_mod_sec_lookup (pc, tsk, &s);
+ m = _stp_mod_sec_lookup (pc, tsk, &s, NULL);
if (unlikely(m == NULL)) {
dbug_unwind(1, "No module found for pc=%lx", pc);
return -EINVAL;
}
dbug_unwind(1, "trying debug_frame\n");
- res = unwind_frame (frame, m, s, m->debug_frame,
+ res = unwind_frame (frame, tsk, m, s, m->debug_frame,
m->debug_frame_len, 0);
if (res != 0) {
dbug_unwind(1, "debug_frame failed: %d, trying eh_frame\n", res);
- res = unwind_frame (frame, m, s, m->eh_frame,
+ res = unwind_frame (frame, tsk, m, s, m->eh_frame,
m->eh_frame_len, 1);
}