Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > b0cbe0f49a5d77255d18d74997a8e96b > files > 9

systemtap-0.9.7-5.el5.src.rpm

From: Mark Wielaard <mjw@redhat.com>
Date: Wed, 3 Jun 2009 13:36:03 +0000 (+0200)
Subject: Detect kretprobe trampoline and use fallback unwinder.
X-Git-Url: http://sourceware.org/git/?p=systemtap.git;a=commitdiff_plain;h=129de
9ef18cd142e31ed509a7704d4faf0879f4c

Detect kretprobe trampoline and use fallback unwinder.

* runtime/sym.h (_stp_kretprobe_trampoline): Document.
* translate.cxx (unwindsym_dump_context): Add stp_kretprobe_trampoline_addr.
  (dump_unwindsyms): Detect kretprobe_trampoline_holder symbol address.
  (emit_symbol_data): Initialize and emit _stp_kretprobe_trampoline.
* runtime/transport/symbols.c (_stp_do_relocation): Detect kernel load
  address and adjust _stp_kretprobe_trampoline.
* runtime/stack-i386.c (__stp_stack_print): Always use fallback unwinder
  when hitting kretprobe_trampoline_holder.
* runtime/stack-x86_64.c (__stp_stack_print): Likewise.
---

diff -ur systemtap-0.9.7.orig/runtime/stack-i386.c systemtap-0.9.7/runtime/stack-i386.c
--- systemtap-0.9.7.orig/runtime/stack-i386.c	2009-04-24 00:11:37.000000000 +0200
+++ systemtap-0.9.7/runtime/stack-i386.c	2009-06-03 17:52:13.000000000 +0200
@@ -67,14 +67,15 @@
 		if (ret == 0) {
 			_stp_func_print(UNW_PC(&info), verbose, 1, tsk);
 			levels--;
-			continue;
+			if (UNW_PC(&info) != _stp_kretprobe_trampoline)
+			  continue;
 		}
 		/* If an error happened or we hit a kretprobe trampoline,
 		 * use fallback backtrace, unless user task backtrace.
 		 * FIXME: is there a way to unwind across kretprobe
-		 * trampolines? */
+		 * trampolines? PR9999. */
 		if ((ret < 0
-		     || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+		     || UNW_PC(&info) == _stp_kretprobe_trampoline)
 		    && ! (tsk || arch_unw_user_mode(&info)))
 			_stp_stack_print_fallback(UNW_SP(&info), verbose, levels);
 		return;
diff -ur systemtap-0.9.7.orig/runtime/stack-x86_64.c systemtap-0.9.7/runtime/stack-x86_64.c
--- systemtap-0.9.7.orig/runtime/stack-x86_64.c	2009-04-24 00:11:37.000000000 +0200
+++ systemtap-0.9.7/runtime/stack-x86_64.c	2009-06-03 17:52:13.000000000 +0200
@@ -41,14 +41,15 @@
 		if (ret == 0) {
 			_stp_func_print(UNW_PC(&info), verbose, 1, tsk);
 			levels--;
-			continue;
+			if (UNW_PC(&info) != _stp_kretprobe_trampoline)
+			  continue;
 		}
 		/* If an error happened or we hit a kretprobe trampoline,
 		 * use fallback backtrace, unless user task backtrace.
 		 * FIXME: is there a way to unwind across kretprobe
-		 * trampolines? */
+		 * trampolines? PR9999. */
 		if ((ret < 0
-		     || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+		     || UNW_PC(&info) == _stp_kretprobe_trampoline)
 		    && ! (tsk || arch_unw_user_mode(&info)))
 			_stp_stack_print_fallback(UNW_SP(&info), verbose, levels);
 		return;
diff -ur systemtap-0.9.7.orig/runtime/sym.h systemtap-0.9.7/runtime/sym.h
--- systemtap-0.9.7.orig/runtime/sym.h	2009-04-24 00:11:37.000000000 +0200
+++ systemtap-0.9.7/runtime/sym.h	2009-06-03 17:52:13.000000000 +0200
@@ -59,10 +59,10 @@
 static struct _stp_module *_stp_modules [];
 static unsigned _stp_num_modules;
 
-
-/* the number of modules in the arrays */
-
-static unsigned long _stp_kretprobe_trampoline = 0;
+/* Used in the unwinder to special case unwinding through kretprobes. */
+/* Initialized through translator (stap-symbols.h) relative to kernel */
+/* load address, fixup by transport symbols _stp_do_relocation */
+static unsigned long _stp_kretprobe_trampoline;
 
 static unsigned long _stp_module_relocate (const char *module, const char *section, unsigned long offset);
 static struct _stp_module *_stp_get_unwind_info (unsigned long addr);
Only in systemtap-0.9.7/runtime: sym.h.orig
diff -ur systemtap-0.9.7.orig/runtime/transport/symbols.c systemtap-0.9.7/runtime/transport/symbols.c
--- systemtap-0.9.7.orig/runtime/transport/symbols.c	2009-04-24 00:11:37.000000000 +0200
+++ systemtap-0.9.7/runtime/transport/symbols.c	2009-06-03 17:52:13.000000000 +0200
@@ -30,6 +30,14 @@
 
   dbug_sym(2, "relocate (%s %s 0x%lx)\n", msg.module, msg.reloc, (unsigned long) msg.address);
 
+  /* Detect actual kernel load address. */
+  if (!strcmp ("kernel", msg.module)
+      && !strcmp ("_stext", msg.reloc)) {
+    dbug_sym(2, "found kernel _stext load address: 0x%lx\n",
+             (unsigned long) msg.address);
+    if (_stp_kretprobe_trampoline != (unsigned long) -1)
+      _stp_kretprobe_trampoline += (unsigned long) msg.address;
+  }
 
   /* Save the relocation value.  XXX: While keeping the data here is
      fine for the kernel address space ("kernel" and "*.ko" modules),
diff -ur systemtap-0.9.7.orig/translate.cxx systemtap-0.9.7/translate.cxx
--- systemtap-0.9.7.orig/translate.cxx	2009-04-24 00:11:37.000000000 +0200
+++ systemtap-0.9.7/translate.cxx	2009-06-03 17:52:13.000000000 +0200
@@ -4409,6 +4409,7 @@
   systemtap_session& session;
   ostream& output;
   unsigned stp_module_index;
+  unsigned long stp_kretprobe_trampoline_addr;
   set<string> undone_unwindsym_modules;
 };
 
@@ -4630,6 +4631,11 @@
                   secname = "_stext";
                   // NB: don't subtract session.sym_stext, which could be inconveniently NULL.
                   // Instead, sym_addr will get compensated later via extra_offset.
+
+                  // We need to note this for the unwinder.
+                  if (c->stp_kretprobe_trampoline_addr == (unsigned long) -1
+                      && ! strcmp (name, "kretprobe_trampoline_holder"))
+                    c->stp_kretprobe_trampoline_addr = sym_addr;
                 }
               else if (n > 0)
                 {
@@ -4679,6 +4685,10 @@
         }
     }
 
+  // Must be relative to actual kernel load address.
+  if (c->stp_kretprobe_trampoline_addr != (unsigned long) -1)
+    c->stp_kretprobe_trampoline_addr -= extra_offset;
+
   // Add unwind data to be included if it exists for this module.
   size_t len = 0;
   void *unwind = get_unwind_data (m, &len);
@@ -4826,7 +4836,7 @@
 
   ofstream kallsyms_out ((s.tmpdir + "/" + symfile).c_str());
 
-  unwindsym_dump_context ctx = { s, kallsyms_out, 0, s.unwindsym_modules };
+  unwindsym_dump_context ctx = { s, kallsyms_out, 0, -1, s.unwindsym_modules };
 
   // Micro optimization, mainly to speed up tiny regression tests
   // using just begin probe.
@@ -4944,6 +4954,9 @@
   ctx->output << "};\n";
   ctx->output << "static unsigned _stp_num_modules = " << ctx->stp_module_index << ";\n";
 
+  ctx->output << "static unsigned long _stp_kretprobe_trampoline = 0x"
+	      << hex << ctx->stp_kretprobe_trampoline_addr << dec << ";\n";
+
   // Some nonexistent modules may have been identified with "-d".  Note them.
   for (set<string>::iterator it = ctx->undone_unwindsym_modules.begin();
        it != ctx->undone_unwindsym_modules.end();