diff options
author | David Smith <dsmith@redhat.com> | 2008-04-14 12:53:38 -0500 |
---|---|---|
committer | David Smith <dsmith@redhat.com> | 2008-04-14 12:53:38 -0500 |
commit | ff82a2ca27f4fd0086a911656017e3b912778525 (patch) | |
tree | 17d6946329f0e52b2201bd1fcda52d2069a731fd /runtime/staprun | |
parent | 43807f81b6365864e047583eaebe5e85588c7b36 (diff) | |
parent | 775d51e5fb2f379fe4ae15dcbae8b17e4eab8805 (diff) | |
download | systemtap-steved-ff82a2ca27f4fd0086a911656017e3b912778525.tar.gz systemtap-steved-ff82a2ca27f4fd0086a911656017e3b912778525.tar.xz systemtap-steved-ff82a2ca27f4fd0086a911656017e3b912778525.zip |
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime/staprun')
-rw-r--r-- | runtime/staprun/mainloop.c | 159 | ||||
-rw-r--r-- | runtime/staprun/staprun.c | 3 | ||||
-rw-r--r-- | runtime/staprun/staprun.h | 3 | ||||
-rw-r--r-- | runtime/staprun/staprun_funcs.c | 92 | ||||
-rw-r--r-- | runtime/staprun/unwind_data.c | 97 |
5 files changed, 182 insertions, 172 deletions
diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 2e0c3c5c..1dcb6b00 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -27,7 +27,7 @@ static void sigproc(int signum) return; send_request(STP_EXIT, NULL, 0); } else if (signum == SIGQUIT) - cleanup_and_exit(2); + cleanup_and_exit(2); else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM) send_request(STP_EXIT, NULL, 0); } @@ -40,7 +40,7 @@ static void setup_main_signals(int cleanup) if (cleanup == 0) { a.sa_handler = sigproc; sigaction(SIGCHLD, &a, NULL); - } else + } else a.sa_handler = SIG_IGN; sigaction(SIGINT, &a, NULL); sigaction(SIGTERM, &a, NULL); @@ -48,7 +48,6 @@ static void setup_main_signals(int cleanup) sigaction(SIGQUIT, &a, NULL); } - /* * start_cmd forks the command given on the command line * with the "-c" option. It will not exec that command @@ -75,7 +74,7 @@ void start_cmd(void) a.sa_handler = SIG_IGN; sigaction(SIGINT, &a, NULL); - dbug (1, "execing target_cmd %s\n", target_cmd); + dbug(1, "execing target_cmd %s\n", target_cmd); if ((pid = fork()) < 0) { _perr("fork"); exit(1); @@ -86,8 +85,8 @@ void start_cmd(void) sigaction(SIGINT, &a, NULL); /* commands we fork need to run at normal priority */ - setpriority (PRIO_PROCESS, 0, 0); - + setpriority(PRIO_PROCESS, 0, 0); + /* wait here until signaled */ sigwait(&usrset, &signum); @@ -107,11 +106,11 @@ void system_cmd(char *cmd) { pid_t pid; - dbug (2, "system %s\n", cmd); + dbug(2, "system %s\n", cmd); if ((pid = fork()) < 0) { _perr("fork"); } else if (pid == 0) { - setpriority (PRIO_PROCESS, 0, 0); + setpriority(PRIO_PROCESS, 0, 0); if (execl("/bin/sh", "sh", "-c", cmd, NULL) < 0) perr("%s", cmd); _exit(1); @@ -128,7 +127,7 @@ static void read_buffer_info(void) if (!use_old_transport) return; - if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) + if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) return; if (sprintf_chk(buf, "/proc/systemtap/%s/bufsize", modname)) @@ -152,7 +151,6 @@ static void read_buffer_info(void) return; } - /** * init_stapio - initialize the app * @print_summary: boolean, print summary or not at end of run @@ -177,7 +175,7 @@ int init_stapio(void) if (init_oldrelayfs() < 0) { close_ctl_channel(); return -1; - } + } } else { if (init_relayfs() < 0) { close_ctl_channel(); @@ -192,7 +190,6 @@ int init_stapio(void) if (target_cmd) start_cmd(); - return 0; } @@ -202,7 +199,7 @@ int init_stapio(void) * 2 - disconnected * 3 - initialized */ -void cleanup_and_exit (int closed) +void cleanup_and_exit(int closed) { pid_t err; static int exiting = 0; @@ -219,7 +216,7 @@ void cleanup_and_exit (int closed) err = waitpid(-1, NULL, WNOHANG); if (err >= 0) err("\nWaiting for processes to exit\n"); - while(wait(NULL) > 0) ; + while (wait(NULL) > 0) ; if (use_old_transport) close_oldrelayfs(closed == 2); @@ -230,8 +227,7 @@ void cleanup_and_exit (int closed) close_ctl_channel(); if (initialized == 2 && closed == 2) { - err("\nDisconnecting from systemtap module.\n" \ - "To reconnect, type \"staprun -A %s\"\n", modname); + err("\nDisconnecting from systemtap module.\n" "To reconnect, type \"staprun -A %s\"\n", modname); } else if (initialized) closed = 3; else @@ -247,7 +243,7 @@ int stp_main_loop(void) { ssize_t nb; void *data; - int type; + uint32_t type; FILE *ofp = stdout; char recvbuf[8196]; @@ -257,80 +253,93 @@ int stp_main_loop(void) dbug(2, "in main loop\n"); send_request(STP_READY, NULL, 0); - while (1) { /* handle messages from control channel */ + while (1) { /* handle messages from control channel */ nb = read(control_channel, recvbuf, sizeof(recvbuf)); if (nb <= 0) { if (errno != EINTR) _perr("Unexpected EOF in read (nb=%ld)", (long)nb); continue; } - - type = *(int *)recvbuf; - data = (void *)(recvbuf + sizeof(int)); - switch (type) { + type = *(uint32_t *)recvbuf; + data = (void *)(recvbuf + sizeof(uint32_t)); + nb -= sizeof(uint32_t); + + switch (type) { #ifdef STP_OLD_TRANSPORT case STP_REALTIME_DATA: - { - ssize_t bw = write(out_fd[0], data, nb - sizeof(int)); - if (bw >= 0 && bw != (nb - (ssize_t)sizeof(int))) { - nb = nb - bw; - bw = write(out_fd[0], data, nb - sizeof(int)); - } - if (bw != (nb - (ssize_t)sizeof(int))) { - _perr("write error (nb=%ld)", (long)nb); - cleanup_and_exit(1); + { + ssize_t bw = write(out_fd[0], data, nb); + if (bw >= 0 && bw != nb) { + nb = nb - bw; + bw = write(out_fd[0], data, nb); + } + if (bw != nb) { + _perr("write error (nb=%ld)", (long)nb); + cleanup_and_exit(1); + } + break; } - break; - } #endif case STP_OOB_DATA: - fputs ((char *)data, stderr); - break; - 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); - break; - } - case STP_START: - { - struct _stp_msg_start *t = (struct _stp_msg_start *)data; - dbug(2, "probe_start() returned %d\n", t->res); - if (t->res < 0) { - if (target_cmd) - kill (target_pid, SIGKILL); - cleanup_and_exit(1); - } else if (target_cmd) - kill (target_pid, SIGUSR1); + fputs((char *)data, stderr); break; - } + 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); + break; + } + case STP_START: + { + struct _stp_msg_start *t = (struct _stp_msg_start *)data; + dbug(2, "probe_start() returned %d\n", t->res); + if (t->res < 0) { + if (target_cmd) + kill(target_pid, SIGKILL); + cleanup_and_exit(1); + } else if (target_cmd) + kill(target_pid, SIGUSR1); + break; + } case STP_SYSTEM: - { - struct _stp_msg_cmd *c = (struct _stp_msg_cmd *)data; - dbug(2, "STP_SYSTEM: %s\n", c->cmd); - system_cmd(c->cmd); - break; - } + { + struct _stp_msg_cmd *c = (struct _stp_msg_cmd *)data; + dbug(2, "STP_SYSTEM: %s\n", c->cmd); + system_cmd(c->cmd); + break; + } case STP_TRANSPORT: - { - struct _stp_msg_start ts; - if (use_old_transport) { - if (init_oldrelayfs() < 0) - cleanup_and_exit(1); - } else { - if (init_relayfs() < 0) - cleanup_and_exit(1); + { + struct _stp_msg_start ts; + if (use_old_transport) { + if (init_oldrelayfs() < 0) + cleanup_and_exit(1); + } else { + if (init_relayfs() < 0) + cleanup_and_exit(1); + } + ts.target = target_pid; + initialized = 2; + send_request(STP_START, &ts, sizeof(ts)); + if (load_only) + cleanup_and_exit(2); + break; + } + case STP_UNWIND: + { + int len; + char *ptr = (char *)data; + while (nb > 0) { + send_unwind_data(ptr); + len = strlen(ptr) + 1; + ptr += len; + nb -= len; + } + break; } - ts.target = target_pid; - initialized = 2; - send_request(STP_START, &ts, sizeof(ts)); - if (load_only) - cleanup_and_exit(2); - break; - } default: err("WARNING: ignored message of type %d\n", (type)); } diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index f4e67fdb..8db2ac5b 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -181,8 +181,6 @@ static void cleanup(int rc) if (setpriority (PRIO_PROCESS, 0, 0) < 0) _perr("setpriority"); - stop_symbol_thread(); - /* rc == 2 means disconnected */ if (rc == 2) return; @@ -278,7 +276,6 @@ int main(int argc, char **argv) exit(1); setup_staprun_signals(); - start_symbol_thread(); rc = run_stapio(argv); cleanup(rc); diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 1128fb4c..08797a37 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -118,8 +118,7 @@ int init_stapio(void); int stp_main_loop(void); int send_request(int type, void *data, int len); void cleanup_and_exit (int); -int do_module(void *); -int do_kernel_symbols(void); +void send_unwind_data(const char *name); int init_ctl_channel(int); void close_ctl_channel(void); int init_relayfs(void); diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index 34e12c25..b95a9a5a 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -401,95 +401,3 @@ int check_permissions(void) * is in that directory. */ return check_path(); } - -pthread_t symbol_thread_id = (pthread_t)0; -int kernel_ptr_size = 0; - -/* Symbol handling thread */ -void *handle_symbols(void __attribute__((unused)) *arg) -{ - ssize_t nb; - void *data; - int32_t type; - char recvbuf[8192]; - - dbug(2, "waiting for symbol requests\n"); - - /* handle messages from control channel */ - while (1) { - nb = read(control_channel, recvbuf, sizeof(recvbuf)); - if (nb <= 0) { - if (errno != EINTR) - _perr("Unexpected EOF in read (nb=%ld)", (long)nb); - continue; - } - - type = *(int32_t *)recvbuf; - data = (void *)(recvbuf + sizeof(int32_t)); - - switch (type) { - case STP_MODULE: - { - dbug(2, "STP_MODULES request received\n"); - if (do_module(data) < 0) - goto done; - break; - } - case STP_SYMBOLS: - { - struct _stp_msg_symbol *req = (struct _stp_msg_symbol *)data; - dbug(2, "STP_SYMBOLS request received\n"); - if (req->endian != 0x1234) { - err("ERROR: staprun is compiled with different endianess than the kernel!\n"); - goto done; - } - kernel_ptr_size = req->ptr_size; - if (kernel_ptr_size != 4 && kernel_ptr_size != 8) { - err("ERROR: invalid kernel pointer size %d\n", kernel_ptr_size); - goto done; - } - if (do_kernel_symbols() < 0) - goto done; - break; - } - default: - err("WARNING: ignored message of type %d\n", (type)); - } - } - -done: - /* signal stapio we're done */ - kill(0, SIGINT); - - return NULL; -} - -void start_symbol_thread(void) -{ - int status; - - /* create symbol control channel */ - status = do_cap(CAP_DAC_OVERRIDE, init_ctl_channel, 1); - drop_cap(CAP_DAC_OVERRIDE); - if (status < 0) { - err("Failed to initialize control channel.\n"); - exit(1); - } - status = pthread_create(&symbol_thread_id, NULL, handle_symbols, NULL); - if (status) { - perr("Failed to create symbol thread.\n"); - exit(1); - } -} - -void stop_symbol_thread(void) -{ - - if (symbol_thread_id) { - dbug(2, "Stopping symbol thread.\n"); - pthread_cancel(symbol_thread_id); - pthread_join(symbol_thread_id, NULL); - } - close_ctl_channel(); -} - diff --git a/runtime/staprun/unwind_data.c b/runtime/staprun/unwind_data.c new file mode 100644 index 00000000..ed27cc20 --- /dev/null +++ b/runtime/staprun/unwind_data.c @@ -0,0 +1,97 @@ +/* -*- linux-c -*- + * Unwind data functions for staprun. + * + * Copyright (C) 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" +#include <elfutils/libdwfl.h> +#include <dwarf.h> + +static char debuginfo_path_arr[] = "-:.debug:/usr/lib/debug"; +static char *debuginfo_path = debuginfo_path_arr; +static const Dwfl_Callbacks kernel_callbacks = { + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + .find_elf = dwfl_linux_kernel_find_elf, + .section_address = dwfl_linux_kernel_module_section_address, +}; + +void *get_module_unwind_data(Dwfl * dwfl, const char *name, int *len) +{ + Dwarf_Addr bias = 0; + Dwarf *dw; + GElf_Ehdr *ehdr, ehdr_mem; + GElf_Shdr *shdr, shdr_mem; + Elf_Scn *scn = NULL; + Elf_Data *data = NULL; + + Dwfl_Module *mod = dwfl_report_module(dwfl, name, 0, 0); + dwfl_report_end(dwfl, NULL, NULL); + dw = dwfl_module_getdwarf(mod, &bias); + Elf *elf = dwarf_getelf(dw); + ehdr = gelf_getehdr(elf, &ehdr_mem); + while ((scn = elf_nextscn(elf, scn))) { + shdr = gelf_getshdr(scn, &shdr_mem); + if (strcmp(elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name), ".debug_frame") == 0) { + data = elf_rawdata(scn, NULL); + break; + } + } + + if (data == NULL) { + *len = 0; + dbug(2, "module %s returns NULL\n", name); + return NULL; + } + dbug(2, "module %s returns %d\n", name, (int)data->d_size); + *len = data->d_size; + return data->d_buf; +} + +void send_unwind_data(const char *name) +{ + struct _stp_msg_unwind *un; + int unwind_data_len = 0; + void *unwind_data = NULL; + char *buf; + + dbug(2, "module %s\n", name); + if (strcmp(name, "*")) { + Dwfl *dwfl = dwfl_begin(&kernel_callbacks); + + if (name[0] == 0) + unwind_data = get_module_unwind_data(dwfl, "kernel", &unwind_data_len); + else + unwind_data = get_module_unwind_data(dwfl, name, &unwind_data_len); + + /* yuck */ + buf = (char *)malloc(unwind_data_len + sizeof(*un) + sizeof(uint32_t)); + if (!buf) { + err("malloc failed\n"); + return; + } + memcpy(buf + sizeof(*un) + sizeof(uint32_t), unwind_data, unwind_data_len); + dwfl_end(dwfl); + } else { + buf = (char *)malloc(sizeof(*un) + sizeof(uint32_t)); + if (!buf) { + err("malloc failed\n"); + return; + } + } + + un = (struct _stp_msg_unwind *)(buf + sizeof(uint32_t)); + strncpy(un->name, name, sizeof(un->name)); + un->unwind_len = unwind_data_len; + *(uint32_t *) buf = STP_UNWIND; + + /* send unwind data */ + if (write(control_channel, buf, unwind_data_len + sizeof(*un) + sizeof(uint32_t)) <= 0) + err("write failed\n"); +} |