diff options
author | Martin Hunt <hunt@redhat.com> | 2008-04-21 16:50:52 -0400 |
---|---|---|
committer | Martin Hunt <hunt@redhat.com> | 2008-04-21 16:50:52 -0400 |
commit | b197bf0b2a6267b73edcdbf68c73d259bf6a6e6a (patch) | |
tree | 0daf7bc638ce8f095cbb2251726e71cb52c1fdc3 | |
parent | 159cb10989a9d6c1d28fc5d1fa5506a75046a9f7 (diff) | |
download | systemtap-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.c | 2 | ||||
-rw-r--r-- | runtime/staprun/ChangeLog | 12 | ||||
-rw-r--r-- | runtime/staprun/common.c | 13 | ||||
-rw-r--r-- | runtime/staprun/ctl.c | 31 | ||||
-rw-r--r-- | runtime/staprun/mainloop.c | 64 | ||||
-rw-r--r-- | runtime/staprun/stapio.c | 6 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 163 | ||||
-rw-r--r-- | runtime/staprun/staprun.h | 5 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 12 | ||||
-rw-r--r-- | runtime/staprun/symbols.c | 333 | ||||
-rw-r--r-- | runtime/transport/ChangeLog | 6 | ||||
-rw-r--r-- | runtime/transport/control.c | 2 | ||||
-rw-r--r-- | runtime/transport/transport.c | 15 | ||||
-rw-r--r-- | testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | testsuite/systemtap.samples/args.exp | 4 |
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 |