]> sourceware.org Git - systemtap.git/commitdiff
PR9940: add/use unmap_u[ret]probe
authorJim Keniston <jkenisto@us.ibm.com>
Wed, 15 Apr 2009 23:11:17 +0000 (16:11 -0700)
committerJim Keniston <jkenisto@us.ibm.com>
Wed, 15 Apr 2009 23:11:17 +0000 (16:11 -0700)
For uprobes 1 and 2, add unmap_u[ret]probe() and define UPROBES_API_VERSION=2.
Adapt tapsets.cxx accordingly.

runtime/uprobes/uprobes.c
runtime/uprobes/uprobes.h
runtime/uprobes2/uprobes.c
runtime/uprobes2/uprobes.h
tapsets.cxx

index 9dfb82b9558104a527b6675d6c6dbff297273f00..27e923b84c195003e27e5a167d8b39be1171d433 100644 (file)
@@ -1049,8 +1049,7 @@ fail_tsk:
 }
 EXPORT_SYMBOL_GPL(register_uprobe);
 
-/* See Documentation/uprobes.txt. */
-void unregister_uprobe(struct uprobe *u)
+void __unregister_uprobe(struct uprobe *u, bool remove_bkpt)
 {
        struct task_struct *p;
        struct uprobe_process *uproc;
@@ -1104,10 +1103,13 @@ void unregister_uprobe(struct uprobe *u)
        if (!list_empty(&ppt->uprobe_list))
                goto done;
 
-       /*
-        * The last uprobe at ppt's probepoint is being unregistered.
-        * Queue the breakpoint for removal.
-        */
+       /* The last uprobe at ppt's probepoint is being unregistered. */
+       if (!remove_bkpt) {
+               uprobe_free_probept(ppt);
+               goto done;
+       }
+
+       /* Queue the breakpoint for removal. */
        ppt->state = UPROBE_REMOVING;
        list_add_tail(&ppt->pd_node, &uproc->pending_uprobes);
 
@@ -1132,8 +1134,20 @@ done:
        up_write(&uproc->rwsem);
        uprobe_put_process(uproc);
 }
+
+/* See Documentation/uprobes.txt. */
+void unregister_uprobe(struct uprobe *u)
+{
+       __unregister_uprobe(u, true);
+}
 EXPORT_SYMBOL_GPL(unregister_uprobe);
 
+void unmap_uprobe(struct uprobe *u)
+{
+       __unregister_uprobe(u, false);
+}
+EXPORT_SYMBOL_GPL(unmap_uprobe);
+
 /* Find a surviving thread in uproc.  Runs with uproc->rwsem locked. */
 static struct task_struct *find_surviving_thread(struct uprobe_process *uproc)
 {
@@ -2540,6 +2554,14 @@ void unregister_uretprobe(struct uretprobe *rp)
 }
 EXPORT_SYMBOL_GPL(unregister_uretprobe);
 
+void unmap_uretprobe(struct uretprobe *rp)
+{
+       if (!rp)
+               return;
+       unmap_uprobe(&rp->u);
+}
+EXPORT_SYMBOL_GPL(unmap_uretprobe);
+
 /*
  * uproc->ssol_area has been successfully set up.  Establish the
  * uretprobe trampoline in slot 0.
index 0266cb7d29d685c20a94246b974ff039062311b4..d542420de79c00b88d4f6aca19b61b89c7cfa306 100644 (file)
@@ -35,6 +35,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 
+/* Version 2 includes unmap_u[ret]probe(). */
+#define UPROBES_API_VERSION 2
+
 struct pt_regs;
 
 enum uprobe_type {
@@ -89,6 +92,9 @@ extern void unregister_uprobe(struct uprobe *u);
 /* For runtime, assume uprobes support includes uretprobes. */
 extern int register_uretprobe(struct uretprobe *rp);
 extern void unregister_uretprobe(struct uretprobe *rp);
+/* For PRs 9940, 6852... */
+extern void unmap_uprobe(struct uprobe *u);
+extern void unmap_uretprobe(struct uretprobe *rp);
 
 #ifdef UPROBES_IMPLEMENTATION
 
index a0e9f2fe6eb61ddf2300b1d9b1a128ba7284be4c..9ea053494c0b69b17f01feb3c553ea8b7e1cba4f 100644 (file)
@@ -955,10 +955,15 @@ static int defer_registration(struct uprobe *u, int regflag,
  */
 static struct pid *uprobe_get_tg_leader(pid_t p)
 {
-       struct pid *pid;
+       struct pid *pid = NULL;
 
        rcu_read_lock();
-       pid = find_vpid(p);
+       /*
+        * We need this check because unmap_u[ret]probe() can be called
+        * from a report_death callback, where current->proxy is NULL.
+        */
+       if (current->nsproxy)
+               pid = find_vpid(p);
        if (pid) {
                struct task_struct *t = pid_task(pid, PIDTYPE_PID);
                if (t)
@@ -1138,8 +1143,7 @@ fail_tsk:
 }
 EXPORT_SYMBOL_GPL(register_uprobe);
 
-/* See Documentation/uprobes.txt. */
-void unregister_uprobe(struct uprobe *u)
+void __unregister_uprobe(struct uprobe *u, bool remove_bkpt)
 {
        struct pid *p;
        struct uprobe_process *uproc;
@@ -1193,10 +1197,13 @@ void unregister_uprobe(struct uprobe *u)
        if (!list_empty(&ppt->uprobe_list))
                goto done;
 
-       /*
-        * The last uprobe at ppt's probepoint is being unregistered.
-        * Queue the breakpoint for removal.
-        */
+       /* The last uprobe at ppt's probepoint is being unregistered. */
+       if (!remove_bkpt) {
+               uprobe_free_probept(ppt);
+               goto done;
+       }
+
+       /* Queue the breakpoint for removal. */
        ppt->state = UPROBE_REMOVING;
        list_add_tail(&ppt->pd_node, &uproc->pending_uprobes);
 
@@ -1221,8 +1228,20 @@ done:
        up_write(&uproc->rwsem);
        uprobe_put_process(uproc, false);
 }
+
+/* See Documentation/uprobes.txt. */
+void unregister_uprobe(struct uprobe *u)
+{
+       __unregister_uprobe(u, true);
+}
 EXPORT_SYMBOL_GPL(unregister_uprobe);
 
+void unmap_uprobe(struct uprobe *u)
+{
+       __unregister_uprobe(u, false);
+}
+EXPORT_SYMBOL_GPL(unmap_uprobe);
+
 /* Find a surviving thread in uproc.  Runs with uproc->rwsem locked. */
 static struct task_struct *find_surviving_thread(struct uprobe_process *uproc)
 {
@@ -2718,6 +2737,14 @@ void unregister_uretprobe(struct uretprobe *rp)
 }
 EXPORT_SYMBOL_GPL(unregister_uretprobe);
 
+void unmap_uretprobe(struct uretprobe *rp)
+{
+       if (!rp)
+               return;
+       unmap_uprobe(&rp->u);
+}
+EXPORT_SYMBOL_GPL(unmap_uretprobe);
+
 /*
  * uproc->ssol_area has been successfully set up.  Establish the
  * uretprobe trampoline in the next available slot following the
index 112e29e2a4b67ba682c83b7c9670ce2911acef5b..ae0692f04235a0835354c57b87a937ff8a6251b0 100644 (file)
@@ -28,6 +28,9 @@
 #define utrace_attached_engine utrace_engine
 #endif
 
+/* Version 2 includes unmap_u[ret]probe(). */
+#define UPROBES_API_VERSION 2
+
 struct pt_regs;
 
 enum uprobe_type {
@@ -82,6 +85,9 @@ extern void unregister_uprobe(struct uprobe *u);
 /* For runtime, assume uprobes support includes uretprobes. */
 extern int register_uretprobe(struct uretprobe *rp);
 extern void unregister_uretprobe(struct uretprobe *rp);
+/* For PRs 9940, 6852... */
+extern void unmap_uprobe(struct uprobe *u);
+extern void unmap_uretprobe(struct uretprobe *rp);
 
 #ifdef UPROBES_IMPLEMENTATION
 
index c63151e1185b444dc2fc6196ce3ec67d13b72f35..1f38023ce88a9c8d0a0b457e31808d89649ee22e 100644 (file)
@@ -7590,6 +7590,9 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "#else";
   s.op->newline() << "#include \"uprobes/uprobes.h\"";
   s.op->newline() << "#endif";
+  s.op->newline() << "#ifndef UPROBES_API_VERSION";
+  s.op->newline() << "#define UPROBES_API_VERSION 1";
+  s.op->newline() << "#endif";
 
   s.op->newline() << "#ifndef MULTIPLE_UPROBES";
   s.op->newline() << "#define MULTIPLE_UPROBES 256"; // maximum possible armed uprobes per process() probe point
@@ -7701,10 +7704,11 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
 
   // register new uprobe
   s.op->newline() << "if (register_p && sup->spec_index < 0) {";
-  // PR6829: we need to check that the sup we're about to reuse is really completely free.
-  // See PR6829 notes below.
-  s.op->newline(1) << "if (sup->spec_index == -1 && sup->up.kdata != NULL) continue;";
+  s.op->newline(1) << "#if (UPROBES_API_VERSION < 2)";
+  // See PR6829 comment.
+  s.op->newline() << "if (sup->spec_index == -1 && sup->up.kdata != NULL) continue;";
   s.op->newline() << "else if (sup->spec_index == -2 && sup->urp.u.kdata != NULL) continue;";
+  s.op->newline() << "#endif";
   s.op->newline() << "sup->spec_index = spec_index;";
   s.op->newline() << "slotted_p = 1;";
   s.op->newline() << "break;";
@@ -7755,13 +7759,32 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
 
   s.op->newline(-1) << "} else if (!register_p && slotted_p) {";
   s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[i];";
-  // NB: we need to release this slot, so we need to borrow the mutex temporarily.
+  s.op->newline() << "int unregistered_flag;";
+  // PR6829, PR9940:
+  // Here we're unregistering for one of two reasons:
+  // 1. the process image is going away (or gone) due to exit or exec; or
+  // 2. the vma containing the probepoint has been unmapped.
+  // In case 1, it's sort of a nop, because uprobes will notice the event
+  // and dispose of the probes eventually, if it hasn't already.  But by
+  // calling unmap_u[ret]probe() ourselves, we free up sup right away.
+  //
+  // In both cases, we must use unmap_u[ret]probe instead of
+  // unregister_u[ret]probe, so uprobes knows not to try to restore the
+  // original opcode.
+  s.op->newline() << "#if (UPROBES_API_VERSION >= 2)";
+  s.op->newline() << "if (sups->return_p)";
+  s.op->newline(1) << "unmap_uretprobe (& sup->urp);";
+  s.op->newline(-1) << "else";
+  s.op->newline(1) << "unmap_uprobe (& sup->up);";
+  s.op->newline(-1) << "unregistered_flag = -1;";
+  s.op->newline() << "#else";
+  // Uprobes lacks unmap_u[ret]probe.  Before reusing sup, we must wait
+  // until uprobes turns loose of the u[ret]probe on its own, as indicated
+  // by uprobe.kdata = NULL.
+  s.op->newline() << "unregistered_flag = (sups->return_p ? -2 : -1);";
+  s.op->newline() << "#endif";
   s.op->newline() << "mutex_lock (& stap_uprobes_lock);";
-  // NB: We must not actually uregister u[ret]probes when a target process execs or exits;
-  // uprobes does that by itself asynchronously.  We can reuse the up/urp struct after
-  // uprobes clears the sup->{up,urp}->kdata pointer. PR6829.  To tell the two
-  // cases apart, we use spec_index -2 vs -1.
-  s.op->newline() << "sup->spec_index = (sups->return_p ? -2 : -1);";
+  s.op->newline() << "sup->spec_index = unregistered_flag;";
   s.op->newline() << "mutex_unlock (& stap_uprobes_lock);";
   s.op->newline() << "handled_p = 1;";
   s.op->newline(-1) << "}"; // if slotted_p
This page took 0.040665 seconds and 5 git commands to generate.