diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-12-21 13:02:19 +0100 |
---|---|---|
committer | Tim Moore <timoore@redhat.com> | 2009-12-22 23:44:29 +0100 |
commit | 2d0ddea123e8d5d1113b80692689a80f37d46e6f (patch) | |
tree | 5ee08c296fddf8f681b065ac9b3b1383866da915 /runtime/task_finder_vma.c | |
parent | 7f24dd744bc6dbef16024c2ec3cbb0ee8e0d4ee5 (diff) | |
download | systemtap-steved-2d0ddea123e8d5d1113b80692689a80f37d46e6f.tar.gz systemtap-steved-2d0ddea123e8d5d1113b80692689a80f37d46e6f.tar.xz systemtap-steved-2d0ddea123e8d5d1113b80692689a80f37d46e6f.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/task_finder_vma.c')
-rw-r--r-- | runtime/task_finder_vma.c | 71 |
1 files changed, 67 insertions, 4 deletions
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; +} |