diff options
author | Stan Cox <scox@redhat.com> | 2009-12-08 11:57:00 -0500 |
---|---|---|
committer | Stan Cox <scox@redhat.com> | 2009-12-08 11:57:00 -0500 |
commit | 63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7 (patch) | |
tree | 2c696530833b8fbe560e29daacd0fb9b2f71fe54 /tapset-utrace.cxx | |
parent | 851418deb65964ef73f55e2aab0f3733c0e0e2e8 (diff) | |
download | systemtap-steved-63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7.tar.gz systemtap-steved-63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7.tar.xz systemtap-steved-63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7.zip |
Add .library("lib").mark("mark") and use it for .mark semaphores.
tapset-utrace.cxx (TOK_LIBRARY): New.
(utrace_derived_probe::utrace_derived_probe): Add library and has_library.
(utrace_builder::build): Handle library.
(utrace_derived_probe_group::emit_probe_decl): Add sdt_sem_offset to
emitted stap_utrace_probes. Add stap_task_finder_target
mmap_callback for handling shared library. Handle sdt_sem_offset in
emitted_stp_utrace_probe_cb. Add stap_utrace_mmap_found.
(register_tapset_utrace): Handle .library
tapset-utrace.cxx (TOK_LIBRARY): New.
(base_query::base_query): Add path and has_library.
(dwarf_derived_probe::dwarf_derived_probe) Likewise.
(dwarf_derived_probe::register_patterns): Handle .library
(sdt_query::convert_location): Likewise.
(dwarf_builder::build): Likewise.
(uprobe_derived_probe_group::emit_module_decls): Emit
sdt_sem_address. Add sdt_sem_offset to emitted stap_uprobe_spec.
Add offset and vm_flags to signature of stap_uprobe_change_plus, and
handle sdt_sem_offset. Allow writeable segments in emitted
stap_uprobe_mmap_found.
sdt_misc.exp: Test .library
util.cxx (find_executable): Add env_path to sig and use it in getenv.
util.h (find_executable): Likewise. Make "PATH" the default.
dtrace.in (provider): Turn on semaphores.
sdt.h: Likewise.
Diffstat (limited to 'tapset-utrace.cxx')
-rw-r--r-- | tapset-utrace.cxx | 102 |
1 files changed, 88 insertions, 14 deletions
diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 795d88b7..bd668a2b 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -29,6 +29,7 @@ static const string TOK_END("end"); static const string TOK_THREAD("thread"); static const string TOK_SYSCALL("syscall"); static const string TOK_RETURN("return"); +static const string TOK_LIBRARY("library"); // ------------------------------------------------------------------------ @@ -52,13 +53,15 @@ struct utrace_derived_probe: public derived_probe { bool has_path; string path; + bool has_library; + string library; int64_t pid; enum utrace_derived_probe_flags flags; bool target_symbol_seen; utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, - bool hp, string &pn, int64_t pd, - enum utrace_derived_probe_flags f); + bool hp, string &pn, bool hl, string &ln, + int64_t pd, enum utrace_derived_probe_flags f); void join_group (systemtap_session& s); void emit_unprivileged_assertion (translator_output*); @@ -115,10 +118,10 @@ struct utrace_var_expanding_visitor: public var_expanding_visitor utrace_derived_probe::utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, - bool hp, string &pn, int64_t pd, - enum utrace_derived_probe_flags f): + bool hp, string &pn, bool hl, string &ln, + int64_t pd, enum utrace_derived_probe_flags f): derived_probe (p, new probe_point (*l) /* .components soon rewritten */ ), - has_path(hp), path(pn), pid(pd), flags(f), + has_path(hp), path(pn), has_library(hl), library(ln), pid(pd), flags(f), target_symbol_seen(false) { if (s.kernel_config["CONFIG_UTRACE"] != string("y")) @@ -599,9 +602,11 @@ struct utrace_builder: public derived_probe_builder vector<derived_probe *> & finished_results) { string path; + string lib; int64_t pid; bool has_path = get_param (parameters, TOK_PROCESS, path); + bool has_lib = get_param (parameters, TOK_LIBRARY, lib); bool has_pid = get_param (parameters, TOK_PROCESS, pid); enum utrace_derived_probe_flags flags = UDPF_NONE; @@ -647,9 +652,11 @@ struct utrace_builder: public derived_probe_builder // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere? } + if (has_lib) + lib = find_executable (lib, "LD_LIBRARY_PATH"); finished_results.push_back(new utrace_derived_probe(sess, base, location, - has_path, path, pid, + has_path, path, has_lib, lib, pid, flags)); } @@ -750,11 +757,25 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, s.op->line() << " .engine_attached=0,"; if (p->sdt_semaphore_addr != 0) - s.op->line() << " .sdt_sem_address=(unsigned long)0x" + s.op->line() << " .sdt_sem_offset=(unsigned long)0x" << hex << p->sdt_semaphore_addr << dec << "ULL,"; - + s.op->line() << " .sdt_sem_address=0,"; s.op->line() << " .tsk=0,"; s.op->line() << " },"; + + if (p->has_library && p->sdt_semaphore_addr != 0) + { + s.op->newline() << "{"; + s.op->line() << " .tgt={"; + s.op->line() << " .procname=\"" << p->path << "\","; + s.op->line() << " .mmap_callback=&stap_utrace_mmap_found,"; + s.op->line() << " },"; + s.op->line() << " .pathname=\"" << p->library << "\","; + s.op->line() << " .sdt_sem_offset=(unsigned long)0x" + << hex << p->sdt_semaphore_addr << dec << "ULL,"; + s.op->line() << " .sdt_sem_address=0,"; + s.op->line() << " },"; + } } @@ -789,7 +810,11 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "struct utrace_engine_ops ops;"; s.op->newline() << "unsigned long events;"; s.op->newline() << "struct task_struct *tsk;"; + s.op->newline() << "unsigned long sdt_sem_offset;"; + // FIXME: if this probe is attached to more than 1 task, having 1 + // address here won't work s.op->newline() << "unsigned long sdt_sem_address;"; + s.op->newline(0) << "const char *pathname;"; s.op->newline(-1) << "};"; @@ -913,15 +938,23 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->indent(-1); s.op->newline(-1) << "}"; + s.op->newline() << "if (p->sdt_sem_offset && p->sdt_sem_address == 0) {"; + s.op->indent(1); + // If the probe is in the executable itself, the offset *is* the address. + s.op->newline() << "p->sdt_sem_address = p->sdt_sem_offset;"; + s.op->newline(-1) << "}"; + + // Before writing to the semaphore, we need to check for VM_WRITE access. s.op->newline() << "if (p->sdt_sem_address != 0) {"; s.op->newline(1) << "size_t sdt_semaphore;"; // XXX p could get registered to more than one task! s.op->newline() << "p->tsk = tsk;"; - s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; - s.op->newline() << "sdt_semaphore += 1;"; + + s.op->newline() << "if (__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0) == sizeof (sdt_semaphore)) {"; + s.op->newline(1) << "sdt_semaphore ++;"; s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; s.op->newline(-1) << "}"; - + s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't @@ -985,6 +1018,44 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; + // The task_finder_mmap_callback + s.op->newline() << "static int stap_utrace_mmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, char *path, unsigned long addr, unsigned long length, unsigned long offset, unsigned long vm_flags) {"; + s.op->newline(1) << "struct stap_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);"; + s.op->newline() << "int rc = 0;"; + // the shared library we're interested in + s.op->newline() << "if (path == NULL || strcmp (path, p->pathname)) return 0;"; + s.op->newline() << "if (p->sdt_sem_address == 0) {"; + s.op->indent(1); + // If the probe is in the executable itself, the offset *is* the + // address. + s.op->newline() << "if (vm_flags & VM_EXECUTABLE) {"; + s.op->indent(1); + s.op->newline() << "p->sdt_sem_address = addr + p->sdt_sem_offset;"; + s.op->newline(-1) << "}"; + // If the probe is in a .so, we have to calculate the address. + s.op->newline() << "else {"; + s.op->indent(1); + s.op->newline() << "p->sdt_sem_address = (addr - offset) + p->sdt_sem_offset;"; + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; + + s.op->newline() << "if (p->sdt_sem_address) {"; + s.op->newline(1) << "unsigned short sdt_semaphore = 0;"; // NB: fixed size + s.op->newline() << "if (__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0) == sizeof (sdt_semaphore)) {"; + + s.op->newline(1) << "if (vm_flags & VM_WRITE) {"; + s.op->indent(1); + s.op->newline() << "sdt_semaphore ++;"; + s.op->newline() << "#ifdef DEBUG_UTRACE"; + s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"+semaphore %#x @ %#lx\\n\", sdt_semaphore, p->sdt_sem_address);"; + s.op->newline() << "#endif"; + s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; + s.op->newline() << "return 0;"; + s.op->newline(-1) << "}"; + s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -1055,14 +1126,15 @@ utrace_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "if (p->engine_attached) {"; s.op->newline(1) << "stap_utrace_detach_ops(&p->ops);"; + // Before writing to the semaphore, we need to check for VM_WRITE access. s.op->newline() << "if (p->sdt_sem_address) {"; s.op->newline(1) << "size_t sdt_semaphore;"; // XXX p could get registered to more than one task! - s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; - s.op->newline() << "sdt_semaphore -= 1;"; + s.op->newline() << "if (__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0) == sizeof (sdt_semaphore)) {"; + s.op->newline(1) << "sdt_semaphore --;"; s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; s.op->newline(-1) << "}"; - + s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; @@ -1094,6 +1166,8 @@ register_tapset_utrace(systemtap_session& s) ->bind(builder); roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN) ->bind(builder); + roots[i]->bind_str(TOK_LIBRARY)->bind(TOK_SYSCALL) + ->bind(builder); } } |