summaryrefslogtreecommitdiffstats
path: root/runtime/staprun/staprun.c
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-07-07 17:40:24 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-07-07 17:40:24 -0400
commitdf00639dbe262b8919bdf625f30d80e5b9b96346 (patch)
tree62e747aaff3b4fa31a90bd15614ca8427ceb611d /runtime/staprun/staprun.c
parentad9ffc6f83dc5b1954c7e4e78cb57b7a3d005281 (diff)
downloadsystemtap-steved-df00639dbe262b8919bdf625f30d80e5b9b96346.tar.gz
systemtap-steved-df00639dbe262b8919bdf625f30d80e5b9b96346.tar.xz
systemtap-steved-df00639dbe262b8919bdf625f30d80e5b9b96346.zip
pass /sys/module/*/sections/* addresses to the kernel module too
Diffstat (limited to 'runtime/staprun/staprun.c')
-rw-r--r--runtime/staprun/staprun.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index cef96815..664b75ee 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -22,6 +22,8 @@
#include "staprun.h"
#include <sys/uio.h>
+#include <glob.h>
+
/* used in dbug, _err and _perr */
@@ -330,6 +332,8 @@ void send_a_relocation (const char* module, const char* reloc, unsigned long lon
int send_relocation_kernel ()
{
+ int srkrc = 0;
+
FILE* kallsyms = fopen ("/proc/kallsyms", "r");
if (kallsyms == NULL)
{
@@ -338,7 +342,8 @@ int send_relocation_kernel ()
}
else
{
- while (! feof(kallsyms))
+ int done_with_kallsyms = 0;
+ while (! feof(kallsyms) && !done_with_kallsyms)
{
char *line = NULL;
size_t linesz = 0;
@@ -352,6 +357,7 @@ int send_relocation_kernel ()
char* symbol = NULL;
int rc = sscanf (line, "%llx %c %as", &address, &type, &symbol);
free (line); line=NULL;
+ if (symbol == NULL) continue; /* OOM? */
#ifdef __powerpc__
#define KERNEL_RELOC_SYMBOL ".__start"
@@ -364,22 +370,92 @@ int send_relocation_kernel ()
send_a_relocation ("kernel", "_stext", address);
/* We need nothing more from the kernel. */
- fclose (kallsyms);
- return 0;
+ done_with_kallsyms=1;
}
- if (symbol != NULL) free (symbol);
+
+ free (symbol);
}
}
fclose (kallsyms);
+ if (!done_with_kallsyms) srkrc = -1;
}
-
- return -1;
+
+ return srkrc;
}
void send_relocation_modules ()
{
- /* XXX */
+ unsigned i;
+ glob_t globbuf;
+ int r = glob("/sys/module/*/sections/*", GLOB_PERIOD, NULL, &globbuf);
+
+ if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
+ return;
+
+ for (i=0; i<globbuf.gl_pathc; i++)
+ {
+ char *module_section_file;
+ char *section_name;
+ char *module_name;
+ char *module_name_end;
+ FILE* secfile;
+ unsigned long long section_address;
+
+ module_section_file = globbuf.gl_pathv[i];
+
+ /* Tokenize the file name.
+ Sample gl_pathv[]: /sys/modules/zlib_deflate/sections/.text
+ Pieces: ^^^^^^^^^^^^ ^^^^^
+ */
+ section_name = rindex (module_section_file, '/');
+ if (! section_name) continue;
+ section_name ++;
+
+ if (!strcmp (section_name, ".")) continue;
+ if (!strcmp (section_name, "..")) continue;
+
+ module_name = index (module_section_file, '/');
+ if (! module_name) continue;
+ module_name ++;
+ module_name = index (module_name, '/');
+ if (! module_name) continue;
+ module_name ++;
+ module_name = index (module_name, '/');
+ if (! module_name) continue;
+ module_name ++;
+
+ module_name_end = index (module_name, '/');
+ if (! module_name_end) continue;
+
+ secfile = fopen (module_section_file, "r");
+ if (! secfile) continue;
+
+ if (1 == fscanf (secfile, "0x%llx", &section_address))
+ {
+ /* Now we destructively modify the string, but by now the file
+ is open so we won't need the full name again. */
+ *module_name_end = '\0';
+
+ send_a_relocation (module_name, section_name, section_address);
+ }
+
+ if (strcmp (section_name, ".gnu.linkonce.this_module"))
+ fclose (secfile);
+ else
+ {
+ set_clexec (fileno (secfile));
+ /* NB: don't fclose this arbitrarily-chosen section file.
+ This forces the kernel to keep a nonzero reference count
+ on the subject module, until staprun exits, by which time
+ the kernel module will have inserted its separate claws
+ into the probeworthy modules. This prevents a race
+ condition where a probe may be just starting up at the
+ same time that a probeworthy module is being unloaded. */
+ }
+ }
+
+ globfree (& globbuf);
}