From efa4888133b8aa360f2ea3a7179f37321a7853ea Mon Sep 17 00:00:00 2001 From: hunt Date: Mon, 21 Jan 2008 17:07:10 +0000 Subject: [PATCH] 2008-01-21 Martin Hunt * symbols.c (send_module): Simplify and use new send_data() function to keep longword alignment. --- runtime/staprun/ChangeLog | 5 ++ runtime/staprun/staprun_funcs.c | 2 - runtime/staprun/symbols.c | 94 ++++++++++++++++++++++++++++----- 3 files changed, 87 insertions(+), 14 deletions(-) diff --git a/runtime/staprun/ChangeLog b/runtime/staprun/ChangeLog index 3f3738636..53545db2f 100644 --- a/runtime/staprun/ChangeLog +++ b/runtime/staprun/ChangeLog @@ -1,3 +1,8 @@ +2008-01-21 Martin Hunt + + * symbols.c (send_module): Simplify and use new send_data() function to keep + longword alignment. + 2008-01-14 Martin Hunt PR4037 and fixes to better synchronize staprun and stapio. diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index ebf05b349..d1bba3f87 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -16,8 +16,6 @@ #include #include -void cleanup(int rc); - void setup_staprun_signals(void) { struct sigaction a; diff --git a/runtime/staprun/symbols.c b/runtime/staprun/symbols.c index 5a4855b30..cf0276ff7 100644 --- a/runtime/staprun/symbols.c +++ b/runtime/staprun/symbols.c @@ -10,19 +10,64 @@ */ #include "staprun.h" +#include +#include /* send symbol data */ -static int send_data(void *data, int len) +static int send_data(int32_t type, void *data, int len) { - int32_t type = STP_SYMBOLS; if (write(control_channel, &type, 4) <= 0) return -1; return write(control_channel, data, len); } +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; +} + + /* 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]*/ +/* [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" @@ -32,8 +77,9 @@ static int get_sections(char *name, char *data_start, int datalen) char filename[STP_MODULE_NAME_LEN + 256]; char buf[32], strdata_start[32768]; char *strdata=strdata_start, *data=data_start; - int fd, len, res; + 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; @@ -64,6 +110,10 @@ static int get_sections(char *name, char *data_start, int datalen) return -1; } + Dwfl *dwfl = dwfl_begin(&kernel_callbacks); + void *unwind_data = get_module_unwind_data (dwfl, name, &unwind_data_len); + mod->unwind_len = unwind_data_len; + while ((d = readdir(secdir))) { char *secname = d->d_name; @@ -139,12 +189,20 @@ static int get_sections(char *name, char *data_start, int datalen) while (len--) *data++ = *strdata++; + if (unwind_data) { + if ((unwind_data_len + data - data_start) > datalen) + goto err0; + memcpy(data, unwind_data, unwind_data_len); + data += unwind_data_len; + } + dwfl_end (dwfl); return data - data_start; err1: close(fd); closedir(secdir); err0: + dwfl_end (dwfl); /* if this happens, something went seriously wrong. */ _err("Unexpected error. Overflowed buffers.\n"); return -1; @@ -158,11 +216,9 @@ static int send_module (char *mname) { char data[65536]; int len; - *(int32_t *)data = STP_MODULE; - len = get_sections(mname, data + sizeof(int32_t), - sizeof(data) - sizeof(int32_t)); + len = get_sections(mname, data, sizeof(data)); if (len > 0) { - if (write(control_channel, data, len + sizeof(int32_t)) <= 0) { + if (send_data(STP_MODULE, data, len) < 0) { _err("Loading of module %s failed. Exiting...\n", mname); return -1; } @@ -195,7 +251,8 @@ int do_module (void *data) return 0; } - return send_module(mod->name); + send_module(mod->name); + return 0; } #define MAX_SYMBOLS 32*1024 @@ -214,7 +271,7 @@ int do_kernel_symbols(void) int ret, num_syms, i = 0, struct_symbol_size; int max_syms= MAX_SYMBOLS, data_basesize = MAX_SYMBOLS*32; - if (kernel_ptr_size == 8) + if (kernel_ptr_size == 8) struct_symbol_size = sizeof(struct _stp_symbol64); else struct_symbol_size = sizeof(struct _stp_symbol32); @@ -288,20 +345,33 @@ int do_kernel_symbols(void) if (num_syms <= 0) goto err; + /* get unwind data */ + int unwind_data_len; + void *unwind_data; + Dwfl *dwfl = dwfl_begin(&kernel_callbacks); + unwind_data = get_module_unwind_data (dwfl, "kernel", &unwind_data_len); + + /* 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)unwind_data_len; if (send_request(STP_SYMBOLS, &smsh, sizeof(smsh)) <= 0) goto err; /* send syms */ - if (send_data(syms, num_syms*struct_symbol_size) < 0) + if (send_data(STP_SYMBOLS, syms, num_syms*struct_symbol_size) < 0) goto err; /* send data */ - if (send_data(data_base, dataptr-data_base) < 0) + if (send_data(STP_SYMBOLS, data_base, dataptr-data_base) < 0) + goto err; + + /* send unwind data */ + if (send_data(STP_SYMBOLS, unwind_data, unwind_data_len) < 0) goto err; + dwfl_end (dwfl); free(data_base); free(syms); -- 2.43.5