summaryrefslogtreecommitdiffstats
path: root/tapset-utrace.cxx
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-12-08 23:34:25 +0100
committerTim Moore <timoore@redhat.com>2009-12-08 23:34:25 +0100
commitf4ba7c13533b7e99edd0e66a0f6ccd6c0f55ec38 (patch)
tree3fdabe20037596c869776f1bff6c4bd3b8e058f0 /tapset-utrace.cxx
parent8cabc8bcdcd22e8726734f1a18f23ed7d9c19e9f (diff)
parent63b4fd1474ec5859fac4c9b710c8f466bcd3b0f7 (diff)
downloadsystemtap-steved-f4ba7c13533b7e99edd0e66a0f6ccd6c0f55ec38.tar.gz
systemtap-steved-f4ba7c13533b7e99edd0e66a0f6ccd6c0f55ec38.tar.xz
systemtap-steved-f4ba7c13533b7e99edd0e66a0f6ccd6c0f55ec38.zip
Merge commit 'origin/master'
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);
}
}