summaryrefslogtreecommitdiffstats
path: root/tapset-utrace.cxx
diff options
context:
space:
mode:
authorStan Cox <scox@redhat.com>2009-12-08 11:57:00 -0500
committerStan Cox <scox@redhat.com>2009-12-08 11:57:00 -0500
commit63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7 (patch)
tree2c696530833b8fbe560e29daacd0fb9b2f71fe54 /tapset-utrace.cxx
parent851418deb65964ef73f55e2aab0f3733c0e0e2e8 (diff)
downloadsystemtap-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.cxx102
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);
}
}