summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Hunt <hunt@redhat.com>2008-04-21 16:50:52 -0400
committerMartin Hunt <hunt@redhat.com>2008-04-21 16:50:52 -0400
commitb197bf0b2a6267b73edcdbf68c73d259bf6a6e6a (patch)
tree0daf7bc638ce8f095cbb2251726e71cb52c1fdc3
parent159cb10989a9d6c1d28fc5d1fa5506a75046a9f7 (diff)
downloadsystemtap-steved-b197bf0b2a6267b73edcdbf68c73d259bf6a6e6a.tar.gz
systemtap-steved-b197bf0b2a6267b73edcdbf68c73d259bf6a6e6a.tar.xz
systemtap-steved-b197bf0b2a6267b73edcdbf68c73d259bf6a6e6a.zip
Change staprun to exec stapio. Add "-d" option to staprun.
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/staprun/ChangeLog12
-rw-r--r--runtime/staprun/common.c13
-rw-r--r--runtime/staprun/ctl.c31
-rw-r--r--runtime/staprun/mainloop.c64
-rw-r--r--runtime/staprun/stapio.c6
-rw-r--r--runtime/staprun/staprun.c163
-rw-r--r--runtime/staprun/staprun.h5
-rw-r--r--runtime/staprun/staprun_funcs.c12
-rw-r--r--runtime/staprun/symbols.c333
-rw-r--r--runtime/transport/ChangeLog6
-rw-r--r--runtime/transport/control.c2
-rw-r--r--runtime/transport/transport.c15
-rw-r--r--testsuite/ChangeLog4
-rw-r--r--testsuite/systemtap.samples/args.exp4
15 files changed, 174 insertions, 498 deletions
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 729b8a2a..783e72bd 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -45,6 +45,6 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels)
break;
}
#else /* ! STP_USE_DWARF_UNWINDER */
- _stp_stack_print_fallback(REG_SP(regs), verbose);
+ _stp_stack_print_fallback(REG_SP(regs), verbose);
#endif
}
diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog
index e9ef2e2d..6b8204f7 100644
--- a/runtime/staprun/ChangeLog
+++ b/runtime/staprun/ChangeLog
@@ -1,3 +1,15 @@
+2008-04-21 Martin Hunt <hunt@redhat.com>
+
+ * staprun.c, stapio.c, staprun.h, mainloop.c, staprun_funcs.c,
+ ctl.c, common.c: Add "-d" option to have staprun remove
+ modules. Have staprun exec stapio and then have stapio
+ exec "staprun -d" to remove the module when finished.
+
+2008-04-16 Martin Hunt <hunt@redhat.com>
+
+ * ctl.c (init_ctl_channel): Remove unused parameter.
+ Just opens one channel now.
+
2008-02-21 David Smith <dsmith@redhat.com>
* staprun_funcs.c (check_path): Small security fix.
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 47778efd..f228caff 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -22,6 +22,7 @@ unsigned int buffer_size;
char *target_cmd;
char *outfile_name;
int attach_mod;
+int delete_mod;
int load_only;
int need_uprobes;
@@ -30,7 +31,6 @@ char *modname = NULL;
char *modpath = "";
char *modoptions[MAXMODOPTIONS];
-int initialized = 0;
int control_channel = 0;
void parse_args(int argc, char **argv)
@@ -44,10 +44,11 @@ void parse_args(int argc, char **argv)
target_cmd = NULL;
outfile_name = NULL;
attach_mod = 0;
+ delete_mod = 0;
load_only = 0;
need_uprobes = 0;
- while ((c = getopt(argc, argv, "ALuvb:t:d:c:o:x:")) != EOF) {
+ while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:")) != EOF) {
switch (c) {
case 'u':
need_uprobes = 1;
@@ -67,7 +68,8 @@ void parse_args(int argc, char **argv)
target_pid = atoi(optarg);
break;
case 'd':
- /* obsolete internal option used by stap */
+ /* delete module */
+ delete_mod = 1;
break;
case 'c':
target_cmd = optarg;
@@ -250,10 +252,7 @@ static void fatal_handler (int signum)
rc = write (STDERR_FILENO, ERR_MSG, sizeof(ERR_MSG));
rc = write (STDERR_FILENO, str, strlen(str));
rc = write (STDERR_FILENO, "\n", 1);
- if (initialized)
- _exit(3);
- else
- _exit(1);
+ _exit(1);
}
void setup_signals(void)
diff --git a/runtime/staprun/ctl.c b/runtime/staprun/ctl.c
index af7e6c1a..15c5c3d3 100644
--- a/runtime/staprun/ctl.c
+++ b/runtime/staprun/ctl.c
@@ -12,38 +12,35 @@
#include "staprun.h"
-int init_ctl_channel(int symbols)
+int init_ctl_channel(const char *name, int verb)
{
- char *cname, buf[PATH_MAX];
+ char buf[PATH_MAX];
struct statfs st;
int old_transport = 0;
-
- if (symbols)
- cname = ".symbols";
- else
- cname = ".cmd";
- if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) {
- if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/%s", modname, cname))
+ if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) {
+ if (sprintf_chk(buf, "/sys/kernel/debug/systemtap/%s/.cmd", name))
return -1;
} else {
old_transport = 1;
- if (sprintf_chk(buf, "/proc/systemtap/%s/%s", modname, cname))
+ if (sprintf_chk(buf, "/proc/systemtap/%s/.cmd", name))
return -1;
}
-
- dbug(2, "Opening %s\n", buf);
+
+ dbug(2, "Opening %s\n", buf);
control_channel = open(buf, O_RDWR);
if (control_channel < 0) {
- if (attach_mod && errno == ENOENT)
- err("ERROR: Can not attach. Module %s not running.\n", modname);
- else
- perr("Couldn't open control channel '%s'", buf);
+ if (verb) {
+ if (attach_mod && errno == ENOENT)
+ err("ERROR: Can not attach. Module %s not running.\n", name);
+ else
+ perr("Couldn't open control channel '%s'", buf);
+ }
return -1;
}
if (set_clexec(control_channel) < 0)
return -1;
-
+
return old_transport;
}
diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c
index 1dcb6b00..f8328268 100644
--- a/runtime/staprun/mainloop.c
+++ b/runtime/staprun/mainloop.c
@@ -15,7 +15,9 @@
/* globals */
int ncpus;
-int use_old_transport = 0;
+static int use_old_transport = 0;
+enum _stp_sig_type { sig_none, sig_done, sig_detach };
+static enum _stp_sig_type got_signal = sig_none;
static void sigproc(int signum)
{
@@ -27,9 +29,9 @@ static void sigproc(int signum)
return;
send_request(STP_EXIT, NULL, 0);
} else if (signum == SIGQUIT)
- cleanup_and_exit(2);
+ got_signal = sig_detach;
else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM)
- send_request(STP_EXIT, NULL, 0);
+ got_signal = sig_done;
}
static void setup_main_signals(int cleanup)
@@ -162,7 +164,7 @@ int init_stapio(void)
dbug(2, "init_stapio\n");
/* create control channel */
- use_old_transport = init_ctl_channel(0);
+ use_old_transport = init_ctl_channel(modname, 1);
if (use_old_transport < 0) {
err("Failed to initialize control channel.\n");
return -1;
@@ -193,13 +195,9 @@ int init_stapio(void)
return 0;
}
-/* cleanup_and_exit() closed channels and frees memory
- * then exits with the following status codes:
- * 1 - failed to initialize.
- * 2 - disconnected
- * 3 - initialized
- */
-void cleanup_and_exit(int closed)
+/* cleanup_and_exit() closed channels, frees memory,
+ * removes the module (if necessary) and exits. */
+void cleanup_and_exit(int detach)
{
pid_t err;
static int exiting = 0;
@@ -210,7 +208,7 @@ void cleanup_and_exit(int closed)
setup_main_signals(1);
- dbug(1, "CLEANUP AND EXIT closed=%d\n", closed);
+ dbug(1, "detach=%d\n", detach);
/* what about child processes? we will wait for them here. */
err = waitpid(-1, NULL, WNOHANG);
@@ -219,20 +217,23 @@ void cleanup_and_exit(int closed)
while (wait(NULL) > 0) ;
if (use_old_transport)
- close_oldrelayfs(closed == 2);
+ close_oldrelayfs(detach);
else
close_relayfs();
dbug(1, "closing control channel\n");
close_ctl_channel();
- if (initialized == 2 && closed == 2) {
+ if (detach) {
err("\nDisconnecting from systemtap module.\n" "To reconnect, type \"staprun -A %s\"\n", modname);
- } else if (initialized)
- closed = 3;
- else
- closed = 1;
- exit(closed);
+ } else {
+ dbug(2, "removing %s\n", modname);
+ if (execl(BINDIR "/staprun", "staprun", "-d", modname, NULL) < 0) {
+ perror(modname);
+ _exit(1);
+ }
+ }
+ _exit(0);
}
/**
@@ -255,13 +256,18 @@ int stp_main_loop(void)
while (1) { /* handle messages from control channel */
nb = read(control_channel, recvbuf, sizeof(recvbuf));
+ dbug(2, "nb=%d\n", (int)nb);
if (nb <= 0) {
- if (errno != EINTR)
+ if (got_signal == sig_done)
+ send_request(STP_EXIT, NULL, 0);
+ else if (got_signal == sig_detach)
+ cleanup_and_exit(1);
+ else if (errno != EINTR)
_perr("Unexpected EOF in read (nb=%ld)", (long)nb);
continue;
}
- type = *(uint32_t *)recvbuf;
+ type = *(uint32_t *) recvbuf;
data = (void *)(recvbuf + sizeof(uint32_t));
nb -= sizeof(uint32_t);
@@ -276,7 +282,7 @@ int stp_main_loop(void)
}
if (bw != nb) {
_perr("write error (nb=%ld)", (long)nb);
- cleanup_and_exit(1);
+ cleanup_and_exit(0);
}
break;
}
@@ -287,9 +293,8 @@ int stp_main_loop(void)
case STP_EXIT:
{
/* module asks us to unload it and exit */
- int *closed = (int *)data;
- dbug(2, "got STP_EXIT, closed=%d\n", *closed);
- cleanup_and_exit(*closed);
+ dbug(2, "got STP_EXIT\n");
+ cleanup_and_exit(0);
break;
}
case STP_START:
@@ -299,7 +304,7 @@ int stp_main_loop(void)
if (t->res < 0) {
if (target_cmd)
kill(target_pid, SIGKILL);
- cleanup_and_exit(1);
+ cleanup_and_exit(0);
} else if (target_cmd)
kill(target_pid, SIGUSR1);
break;
@@ -316,16 +321,15 @@ int stp_main_loop(void)
struct _stp_msg_start ts;
if (use_old_transport) {
if (init_oldrelayfs() < 0)
- cleanup_and_exit(1);
+ cleanup_and_exit(0);
} else {
if (init_relayfs() < 0)
- cleanup_and_exit(1);
+ cleanup_and_exit(0);
}
ts.target = target_pid;
- initialized = 2;
send_request(STP_START, &ts, sizeof(ts));
if (load_only)
- cleanup_and_exit(2);
+ cleanup_and_exit(1);
break;
}
case STP_UNWIND:
diff --git a/runtime/staprun/stapio.c b/runtime/staprun/stapio.c
index ee30a1a1..70e40004 100644
--- a/runtime/staprun/stapio.c
+++ b/runtime/staprun/stapio.c
@@ -58,12 +58,6 @@ int main(int argc, char **argv)
if (init_stapio())
exit(1);
- initialized = 1;
- if (attach_mod) {
- /* already started */
- initialized++;
- }
-
if (stp_main_loop()) {
err("ERROR: Couldn't enter main loop. Exiting.\n");
exit(1);
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index 8db2ac5b..f9ca8e45 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -16,21 +16,18 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Copyright (C) 2005-2007 Red Hat, Inc.
+ * Copyright (C) 2005-2008 Red Hat, Inc.
*
*/
#include "staprun.h"
-int inserted_module = 0;
-
/* used in dbug, _err and _perr */
char *__name__ = "staprun";
extern long delete_module(const char *, unsigned int);
-static int
-run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
+static int run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
{
pid_t pid;
int rstatus;
@@ -42,14 +39,13 @@ run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
err("%s ", argv[i]);
i++;
}
- err("\n");
+ err("\n");
}
if ((pid = fork()) < 0) {
_perr("fork");
return -1;
- }
- else if (pid == 0) {
+ } else if (pid == 0) {
/* Make sure we run as the full user. If we're
* switching to a non-root user, this won't allow
* that process to switch back to root (since the
@@ -79,17 +75,6 @@ run_as(uid_t uid, gid_t gid, const char *path, char *const argv[])
return -1;
}
-/* Keep the uid and gid settings because we will likely */
-/* conditionally restore "-u" */
-static int run_stapio(char **argv)
-{
- uid_t uid = getuid();
- gid_t gid = getgid();
- argv[0] = PKGLIBDIR "/stapio";
-
- return run_as(uid, gid, argv[0], argv);
-}
-
/*
* Module to be inserted has one or more user-space probes. Make sure
* uprobes is enabled.
@@ -132,8 +117,7 @@ static int enable_uprobes(void)
dbug(2, "Inserting uprobes module from SystemTap runtime.\n");
argv[0] = NULL;
- return insert_module(PKGDATADIR "/runtime/uprobes/uprobes.ko",
- NULL, argv);
+ return insert_module(PKGDATADIR "/runtime/uprobes/uprobes.ko", NULL, argv);
}
static int insert_stap_module(void)
@@ -144,6 +128,66 @@ static int insert_stap_module(void)
return insert_module(modpath, bufsize_option, modoptions);
}
+static int remove_module(const char *name, int verb);
+
+static void remove_all_modules(void)
+{
+ char *base;
+ struct statfs st;
+ struct dirent *d;
+ DIR *moddir;
+
+ if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC)
+ base = "/sys/kernel/debug/systemtap";
+ else
+ base = "/proc/systemtap";
+
+ moddir = opendir(base);
+ if (moddir) {
+ while ((d = readdir(moddir)))
+ if (remove_module(d->d_name, 0) == 0)
+ printf("Module %s removed.\n", d->d_name);
+ closedir(moddir);
+ }
+}
+
+static int remove_module(const char *name, int verb)
+{
+ int ret;
+ dbug(2, "%s\n", name);
+
+ if (strcmp(name, "*") == 0) {
+ remove_all_modules();
+ return 0;
+ }
+
+ /* Call init_ctl_channel() which actually attempts an open()
+ * of the control channel. This is better than using access() because
+ * an open on an already open channel will fail, preventing us from attempting
+ * to remove an in-use module.
+ */
+ if (init_ctl_channel(name, 0) < 0) {
+ if (verb)
+ err("Error accessing systemtap module %s: %s\n", name, strerror(errno));
+ return 1;
+ }
+ close_ctl_channel();
+
+ dbug(2, "removing module %s\n", name);
+
+ /* Don't remove module when priority is elevated. */
+ if (setpriority(PRIO_PROCESS, 0, 0) < 0)
+ _perr("setpriority");
+
+ ret = do_cap(CAP_SYS_MODULE, delete_module, name, 0);
+ if (ret != 0) {
+ err("Error removing module '%s': %s.\n", name, strerror(errno));
+ return 1;
+ }
+
+ dbug(1, "Module %s removed.\n", name);
+ return 0;
+}
int init_staprun(void)
{
@@ -154,69 +198,28 @@ int init_staprun(void)
/* We're done with CAP_SYS_ADMIN. */
drop_cap(CAP_SYS_ADMIN);
-
- if (!attach_mod) {
+
+ if (delete_mod)
+ exit(remove_module(modname, 1));
+ else if (!attach_mod) {
if (need_uprobes && enable_uprobes() != 0)
return -1;
if (insert_stap_module() < 0)
return -1;
- else
- inserted_module = 1;
}
-
return 0;
}
-
-static void cleanup(int rc)
-{
- /* Only cleanup once. */
- static int done = 0;
- if (done == 0)
- done = 1;
- else
- return;
-
- dbug(2, "rc=%d, inserted_module=%d\n", rc, inserted_module);
-
- if (setpriority (PRIO_PROCESS, 0, 0) < 0)
- _perr("setpriority");
-
- /* rc == 2 means disconnected */
- if (rc == 2)
- return;
-
- /* If we inserted the module and did not get rc==2, then */
- /* we really want to remove it. */
- if (inserted_module || rc == 3) {
- long ret;
- dbug(2, "removing module %s\n", modname);
- ret = do_cap(CAP_SYS_MODULE, delete_module, modname, 0);
- if (ret != 0)
- err("Error removing module '%s': %s\n", modname, moderror(errno));
- }
-}
-
-static void exit_cleanup(void)
-{
- dbug(2, "something exited...\n");
- cleanup(1);
-}
int main(int argc, char **argv)
{
int rc;
- if (atexit(exit_cleanup)) {
- _perr("cannot set exit function");
- exit(1);
- }
-
- /* NB: Don't do the geteuid()!=0 check here, since we want to
- test command-line error-handling while running non-root. */
+ /* NB: Don't do the geteuid()!=0 check here, since we want to
+ test command-line error-handling while running non-root. */
/* Get rid of a few standard environment variables (which */
/* might cause us to do unintended things). */
rc = unsetenv("IFS") || unsetenv("CDPATH") || unsetenv("ENV")
- || unsetenv("BASH_ENV");
+ || unsetenv("BASH_ENV");
if (rc) {
_perr("unsetenv failed");
exit(-1);
@@ -234,13 +237,13 @@ int main(int argc, char **argv)
dbug(2, "modpath=\"%s\", modname=\"%s\"\n", modpath, modname);
}
- if (optind < argc) {
+ if (optind < argc) {
if (attach_mod) {
err("ERROR: Cannot have module options with attach (-A).\n");
usage(argv[0]);
} else {
unsigned start_idx = 0;
- while (optind < argc && start_idx+1 < MAXMODOPTIONS)
+ while (optind < argc && start_idx + 1 < MAXMODOPTIONS)
modoptions[start_idx++] = argv[optind++];
modoptions[start_idx] = NULL;
}
@@ -252,8 +255,8 @@ int main(int argc, char **argv)
}
if (geteuid() != 0) {
- err("ERROR: The effective user ID of staprun must be set to the root user.\n"
- " Check permissions on staprun and ensure it is a setuid root program.\n");
+ err("ERROR: The effective user ID of staprun must be set to the root user.\n"
+ " Check permissions on staprun and ensure it is a setuid root program.\n");
exit(1);
}
@@ -275,10 +278,14 @@ int main(int argc, char **argv)
if (init_staprun())
exit(1);
- setup_staprun_signals();
-
- rc = run_stapio(argv);
- cleanup(rc);
-
+ argv[0] = PKGLIBDIR "/stapio";
+ if (execv(argv[0], argv) < 0) {
+ perror(argv[0]);
+ goto err;
+ }
return 0;
+
+err:
+ remove_module(modname, 1);
+ return 1;
}
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index 08797a37..6308d302 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -103,8 +103,6 @@ extern char *__name__;
#define STP_OLD_TRANSPORT
#include "../transport/transport_msgs.h"
-extern int use_old_transport;
-
#define RELAYFS_MAGIC 0xF0B4A981
#define DEBUGFS_MAGIC 0x64626720
#define DEBUGFSDIR "/sys/kernel/debug"
@@ -119,7 +117,7 @@ int stp_main_loop(void);
int send_request(int type, void *data, int len);
void cleanup_and_exit (int);
void send_unwind_data(const char *name);
-int init_ctl_channel(int);
+int init_ctl_channel(const char *name, int verb);
void close_ctl_channel(void);
int init_relayfs(void);
void close_relayfs(void);
@@ -168,6 +166,7 @@ extern int target_pid;
extern char *target_cmd;
extern char *outfile_name;
extern int attach_mod;
+extern int delete_mod;
extern int load_only;
extern int need_uprobes;
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index b95a9a5a..c1cb92b7 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -16,18 +16,6 @@
#include <grp.h>
#include <pwd.h>
-void setup_staprun_signals(void)
-{
- struct sigaction a;
- memset(&a, 0, sizeof(a));
- sigfillset(&a.sa_mask);
- a.sa_handler = SIG_IGN;
- sigaction(SIGINT, &a, NULL);
- sigaction(SIGTERM, &a, NULL);
- sigaction(SIGHUP, &a, NULL);
- sigaction(SIGQUIT, &a, NULL);
-}
-
extern long init_module(void *, unsigned long, const char *);
/* Module errors get translated. */
diff --git a/runtime/staprun/symbols.c b/runtime/staprun/symbols.c
deleted file mode 100644
index c7362d9e..00000000
--- a/runtime/staprun/symbols.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/* -*- linux-c -*-
- * Symbols and modules functions for staprun.
- *
- * Copyright (C) 2006-2008 Red Hat Inc.
- *
- * This file is part of systemtap, and is free software. You can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License (GPL); either version 2, or (at your option) any
- * later version.
- */
-
-#include "staprun.h"
-
-/* send symbol data */
-static int send_data(int32_t type, void *data, int len)
-{
- if (write(control_channel, &type, 4) <= 0)
- return -1;
- return write(control_channel, data, len);
-}
-
-
-/* Get the sections for a module. Put them in the supplied buffer */
-/* in the following order: */
-/* [struct _stp_msg_module][struct _stp_symbol sections ...][string data][unwind data] */
-/* Return the total length of all the data. */
-
-#define SECDIR "/sys/module/%s/sections"
-static int get_sections(char *name, char *data_start, int datalen)
-{
- char dir[STP_MODULE_NAME_LEN + sizeof(SECDIR)];
- char filename[STP_MODULE_NAME_LEN + 256];
- char buf[32], strdata_start[32768];
- char *strdata=strdata_start, *data=data_start;
- int fd, len, res, unwind_data_len=0;
- struct _stp_msg_module *mod = (struct _stp_msg_module *)data_start;
-
- struct dirent *d;
- DIR *secdir;
- void *sec;
- int struct_symbol_size = kernel_ptr_size == 8 ? sizeof(struct _stp_symbol64) : sizeof(struct _stp_symbol32);
- uint64_t sec_addr;
-
- /* start of data is a struct _stp_msg_module */
- data += sizeof(struct _stp_msg_module);
-
- res = snprintf(dir, sizeof(dir), SECDIR, name);
- if (res >= (int)sizeof(dir)) {
- _err("Couldn't fit module \"%s\" into dir buffer.\n" \
- "This should never happen. Please file a bug report.\n", name);
- return -1;
- }
-
- if ((secdir = opendir(dir)) == NULL)
- return 0;
-
- /* Initialize mod. */
- memset(mod, 0, sizeof(struct _stp_msg_module));
-
- /* Copy name in and check for overflow. */
- strncpy(mod->name, name, STP_MODULE_NAME_LEN);
- if (mod->name[STP_MODULE_NAME_LEN - 1] != '\0') {
- _err("Couldn't fit module \"%s\" into mod->name buffer.\n" \
- "This should never happen. Please file a bug report.\n", name);
- return -1;
- }
-
- /* FIXME: optionally fill in unwind data here */
- mod->unwind_len = unwind_data_len;
-
- while ((d = readdir(secdir))) {
- char *secname = d->d_name;
-
- /* Copy filename in and check for overflow. */
- res = snprintf(filename, sizeof(filename), "/sys/module/%s/sections/%s", name, secname);
- if (res >= (int)sizeof(filename)) {
- _err("Couldn't fit secname \"%s\" into filename buffer.\n" \
- "This should never happen. Please file a bug report.\n", secname);
- closedir(secdir);
- return -1;
- }
-
- /* filter out some non-useful stuff */
- if (!strncmp(secname,"__",2)
- || !strcmp(secname,".")
- || !strcmp(secname,"..")
- || !strcmp(secname,".module_sig")
- || !strcmp(secname,".modinfo")
- || !strcmp(secname,".strtab")
- || !strcmp(secname,".symtab") ) {
- continue;
- }
- if (!strncmp(secname, ".gnu.linkonce", 13)
- && strcmp(secname, ".gnu.linkonce.this_module"))
- continue;
-
- if ((fd = open(filename,O_RDONLY)) >= 0) {
- if (read(fd, buf, 32) > 0) {
- /* create next section */
- sec = data;
- if (data - data_start + struct_symbol_size > datalen)
- goto err1;
- data += struct_symbol_size;
-
- sec_addr = (uint64_t)strtoull(buf,NULL,16);
- if (kernel_ptr_size == 8) {
- ((struct _stp_symbol64 *)sec)->addr = sec_addr;
- ((struct _stp_symbol64 *)sec)->symbol = (uint64_t)(strdata - strdata_start);
- } else {
- ((struct _stp_symbol32 *)sec)->addr = (uint32_t)sec_addr;
- ((struct _stp_symbol32 *)sec)->symbol = (uint32_t)(strdata - strdata_start);
- }
- mod->num_sections++;
-
- /* now create string data for the
- * section (checking for overflow) */
- if ((strdata - strdata_start + strlen(strdata))
- >= sizeof(strdata_start))
- goto err1;
- strcpy(strdata, secname);
- strdata += strlen(secname) + 1;
-
- /* These sections are used a lot so keep the values handy */
- if (!strcmp(secname, ".data") || !strncmp(secname, ".rodata", 7)) {
- if (mod->data == 0 || sec_addr < mod->data)
- mod->data = sec_addr;
- }
- if (!strcmp(secname, ".text"))
- mod->text = sec_addr;
- if (!strcmp(secname, ".gnu.linkonce.this_module"))
- mod->module = sec_addr;
- }
- close(fd);
- }
- }
- closedir(secdir);
-
- /* consolidate buffers */
- len = strdata - strdata_start;
- if ((len + data - data_start) > datalen)
- goto err0;
- strdata = strdata_start;
- while (len--)
- *data++ = *strdata++;
-
-#if 0
- if (unwind_data_len) {
- if ((unwind_data_len + data - data_start) > datalen)
- goto err0;
- memcpy(data, unwind_data, unwind_data_len);
- data += unwind_data_len;
- }
-#endif
- return data - data_start;
-
-err1:
- close(fd);
- closedir(secdir);
-err0:
- /* if this happens, something went seriously wrong. */
- _err("Unexpected error. Overflowed buffers.\n");
- return -1;
-}
-#undef SECDIR
-
-/*
- * For modules, we send the name, section names, and offsets
- */
-static int send_module (char *mname)
-{
- char data[65536];
- int len;
- len = get_sections(mname, data, sizeof(data));
- if (len > 0) {
- if (send_data(STP_MODULE, data, len) < 0) {
- _err("Loading of module %s failed. Exiting...\n", mname);
- return -1;
- }
- }
- return len;
-}
-
-/*
- * Send either all modules, or a specific one.
- * Returns:
- * >=0 : OK
- * -1 : serious error (exit)
- */
-int do_module (void *data)
-{
- struct _stp_msg_module *mod = (struct _stp_msg_module *)data;
-
- if (mod->name[0] == 0) {
- struct dirent *d;
- DIR *moddir = opendir("/sys/module");
- if (moddir) {
- while ((d = readdir(moddir)))
- if (send_module(d->d_name) < 0) {
- closedir(moddir);
- return -1;
- }
- closedir(moddir);
- }
- send_request(STP_MODULE, data, 1);
- return 0;
- }
-
- return send_module(mod->name);
-}
-
-#define MAX_SYMBOLS 32*1024
-
-/*
- * Read /proc/kallsyms and send all kernel symbols to the
- * systemtap module. Ignore module symbols; the systemtap module
- * can access them directly.
- */
-int do_kernel_symbols(void)
-{
- FILE *kallsyms=NULL;
- char *name, *mod, *dataptr, *datamax, type, *data_base=NULL;
- unsigned long long addr;
- void *syms = NULL;
- int ret, num_syms, i = 0, struct_symbol_size;
- int max_syms= MAX_SYMBOLS, data_basesize = MAX_SYMBOLS*32;
-
- if (kernel_ptr_size == 8)
- struct_symbol_size = sizeof(struct _stp_symbol64);
- else
- struct_symbol_size = sizeof(struct _stp_symbol32);
-
- syms = malloc(max_syms * struct_symbol_size);
- data_base = malloc(data_basesize);
- if (data_base == NULL || syms == NULL) {
- _err("Failed to allocate memory for symbols\n");
- goto err;
- }
- dataptr = data_base;
- datamax = data_base + data_basesize;
-
- kallsyms = fopen ("/proc/kallsyms", "r");
- if (!kallsyms) {
- _perr("Fatal error: Unable to open /proc/kallsyms");
- goto err;
- }
-
- /* put empty string in data */
- *dataptr++ = 0;
-
- while ((ret = fscanf(kallsyms, "%llx %c %as [%as", &addr, &type, &name, &mod))>0
- && dataptr < datamax) {
- if (ret < 3)
- continue;
- if (ret > 3) {
- /* ignore modules */
- free(name);
- free(mod);
- /* modules are loaded above the kernel, so if we */
- /* are getting modules, then we're done. */
- break;
- }
-
- if (type == 't' || type == 'T' || type == 'A') {
- if (kernel_ptr_size == 8) {
- ((struct _stp_symbol64 *)syms)[i].addr = (uint64_t)addr;
- ((struct _stp_symbol64 *)syms)[i].symbol = (uint64_t)(dataptr - data_base);
- } else {
- ((struct _stp_symbol32 *)syms)[i].addr = (uint32_t)addr;
- ((struct _stp_symbol32 *)syms)[i].symbol = (uint32_t)(dataptr - data_base);
- }
- if (dataptr >= datamax - strlen(name)) {
- char *db;
- data_basesize *= 2;
- db = realloc(data_base, data_basesize);
- if (db == NULL) {
- _err("Could not allocate enough space for symbols.\n");
- goto err;
- }
- dataptr = db + (dataptr - data_base);
- datamax = db + data_basesize;
- data_base = db;
- }
- strcpy(dataptr, name);
- dataptr += strlen(name) + 1;
- free(name);
- i++;
- if (i >= max_syms) {
- max_syms *= 2;
- syms = realloc(syms, max_syms*struct_symbol_size);
- if (syms == NULL) {
- _err("Could not allocate enough space for symbols.\n");
- goto err;
- }
- }
- }
- }
- num_syms = i;
- if (num_syms <= 0)
- goto err;
-
-
- /* send header */
- struct _stp_msg_symbol_hdr smsh;
- smsh.num_syms = num_syms;
- smsh.sym_size = (uint32_t)(dataptr - data_base);
- smsh.unwind_size = (uint32_t)0;
- if (send_request(STP_SYMBOLS, &smsh, sizeof(smsh)) <= 0)
- goto err;
-
- /* send syms */
- if (send_data(STP_SYMBOLS, syms, num_syms*struct_symbol_size) < 0)
- goto err;
-
- /* send data */
- if (send_data(STP_SYMBOLS, data_base, dataptr-data_base) < 0)
- goto err;
-
- free(data_base);
- free(syms);
- fclose(kallsyms);
- return 0;
-
-err:
- if (data_base)
- free(data_base);
- if (syms)
- free(syms);
- if (kallsyms)
- fclose(kallsyms);
-
- _err("Loading of symbols failed. Exiting...\n");
- return -1;
-}
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index 807f6eda..b0f2aee8 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,9 @@
+2008-04-21 hunt <hunt@redhat.com>
+
+ * control.c (_stp_ctl_write): Return len + sizeof(int) so
+ sending an empty command doesn't return 0 and look like a failure.
+ * transport.c: _stp_cleanup_and_exit(): Cleanup.
+
2008-04-15 Frank Ch. Eigler <fche@elastic.org>
PR 6410
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index 92334b9c..ca7edf79 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -141,7 +141,7 @@ static int _stp_ctl_write(int type, void *data, unsigned len)
list_add_tail(&bptr->list, &_stp_ctl_ready_q);
spin_unlock_irqrestore(&_stp_ctl_ready_lock, flags);
- return len;
+ return len + sizeof(bptr->type);
}
/* send commands with timeout and retry */
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 7ff9c8c0..1f9a1667 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -74,13 +74,12 @@ void _stp_handle_start(struct _stp_msg_start *st)
/* common cleanup code. */
/* This is called from the kernel thread when an exit was requested */
-/* by staprun or the exit() function. It is also called by transport_close() */
-/* when the module is removed. In that case "dont_rmmod" is set to 1. */
+/* by staprun or the exit() function. */
/* We need to call it both times because we want to clean up properly */
/* when someone does /sbin/rmmod on a loaded systemtap module. */
-static void _stp_cleanup_and_exit(int dont_rmmod)
+static void _stp_cleanup_and_exit(int send_exit)
{
- dbug_trans(1, "cleanup_and_exit (%d)\n", dont_rmmod);
+ dbug_trans(1, "cleanup_and_exit (%d)\n", send_exit);
if (!_stp_exit_called) {
int failures;
@@ -106,8 +105,8 @@ static void _stp_cleanup_and_exit(int dont_rmmod)
utt_trace_startstop(_stp_utt, 0, &utt_seq);
dbug_trans(1, "ctl_send STP_EXIT\n");
- /* tell staprun to exit (if it is still there) */
- _stp_ctl_send(STP_EXIT, &dont_rmmod, sizeof(int));
+ if (send_exit)
+ _stp_ctl_send(STP_EXIT, NULL, 0);
dbug_trans(1, "done with ctl_send STP_EXIT\n");
}
}
@@ -162,7 +161,7 @@ static void _stp_work_queue(void *data)
/* if exit flag is set AND we have finished with probe_start() */
if (unlikely(_stp_exit_flag))
- _stp_cleanup_and_exit(0);
+ _stp_cleanup_and_exit(1);
else if (likely(_stp_attached))
queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER);
}
@@ -176,7 +175,7 @@ static void _stp_work_queue(void *data)
void _stp_transport_close()
{
dbug_trans(1, "%d: ************** transport_close *************\n", current->pid);
- _stp_cleanup_and_exit(1);
+ _stp_cleanup_and_exit(0);
destroy_workqueue(_stp_wq);
_stp_unregister_ctl_channel();
if (_stp_utt)
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index a2382148..123d7a8a 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2008-04-21 Martin Hunt <hunt@redhat.com>
+
+ * systemtap.samples/args.exp: Remove obsolete "-d" option.
+
2008-04-18 David Smith <dsmith@redhat.com>
* systemtap.base/utrace_p4.exp: Added exec probe test.
diff --git a/testsuite/systemtap.samples/args.exp b/testsuite/systemtap.samples/args.exp
index 54647998..8bed7c9e 100644
--- a/testsuite/systemtap.samples/args.exp
+++ b/testsuite/systemtap.samples/args.exp
@@ -47,7 +47,7 @@ if [file exists $modpath] {
return
}
-spawn $staprunpath -d [pid] $modpath foo=hello bar=999
+spawn $staprunpath $modpath foo=hello bar=999
set ok 0
expect {
-timeout 120
@@ -62,7 +62,7 @@ if {$ok == 1} {
fail "$test run 1"
}
-spawn $staprunpath -d [pid] $modpath foo=goodbye bar=0
+spawn $staprunpath $modpath foo=goodbye bar=0
set ok 0
expect {
-timeout 120