diff options
author | Mark Wielaard <mwielaard@redhat.com> | 2008-09-10 12:38:09 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2008-09-10 14:00:31 +0200 |
commit | 61a805842f0ac863affa37245fc012e3cdcb4312 (patch) | |
tree | 41e9e518120cde5d14850e93f6b24ded69b43be4 | |
parent | 09fa543f68b023479fb3705fe2544ec257368201 (diff) | |
download | systemtap-steved-61a805842f0ac863affa37245fc012e3cdcb4312.tar.gz systemtap-steved-61a805842f0ac863affa37245fc012e3cdcb4312.tar.xz systemtap-steved-61a805842f0ac863affa37245fc012e3cdcb4312.zip |
Get and output unwind data during translate.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | translate.cxx | 82 |
2 files changed, 87 insertions, 0 deletions
@@ -1,3 +1,8 @@ +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * translate.cxx (get_unwind_data): New function. + (dump_unwindsyms): Output unwind data. + 2008-09-09 Masami Hiramatsu <mhiramat@redhat.com> * stapprobes.5.in: Added a description about $return. diff --git a/translate.cxx b/translate.cxx index e5435fac..d4507a1f 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4340,6 +4340,43 @@ struct unwindsym_dump_context }; +// Get the .debug_frame section for the given module. +// l will be set to the length of the size of the unwind data if found. +static void *get_unwind_data (Dwfl_Module *m, size_t *l) +{ + Dwarf_Addr bias = 0; + Dwarf *dw; + GElf_Ehdr *ehdr, ehdr_mem; + GElf_Shdr *shdr, shdr_mem; + Elf_Scn *scn = NULL; + Elf_Data *data = NULL; + + dw = dwfl_module_getdwarf(m, &bias); + if (dw != NULL) + { + 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) + { + *l = data->d_size; + return data->d_buf; + } + + return NULL; +} + static int dump_unwindsyms (Dwfl_Module *m, void **userdata __attribute__ ((unused)), @@ -4459,6 +4496,31 @@ dump_unwindsyms (Dwfl_Module *m, } } + // Add unwind data to be included if it exists for this module. + size_t len = 0; + void *unwind = get_unwind_data (m, &len); + if (unwind != NULL) + { + c->output << "#ifdef STP_USE_DWARF_UNWINDER" << endl; + c->output << "static uint8_t _stp_module_" << stpmod_idx + << "_unwind_data[] = " << endl; + c->output << " {"; + for (size_t i = 0; i < len; i++) + { + int h = ((uint8_t *)unwind)[i]; + c->output << "0x" << hex << h << dec << ","; + if ((i + 1) % 16 == 0) + c->output << endl << " "; + } + c->output << "};" << endl; + c->output << "#endif /* STP_USE_DWARF_UNWINDER */" << endl; + } + else + { + c->session.print_warning ("No unwind data for " + modname + + ", " + dwfl_errmsg (-1)); + } + for (unsigned secidx = 0; secidx < seclist.size(); secidx++) { c->output << "struct _stp_symbol " @@ -4489,6 +4551,26 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl; c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl; + + if (unwind != NULL) + { + c->output << "#ifdef STP_USE_DWARF_UNWINDER" << endl; + c->output << ".unwind_data = " + << "_stp_module_" << stpmod_idx << "_unwind_data, " << endl; + c->output << ".unwind_data_len = " << len << ", " << endl; + c->output << "#else" << endl; + } + + c->output << ".unwind_data = NULL, " << endl; + c->output << ".unwind_data_len = 0, " << endl; + + if (unwind != NULL) + c->output << "#endif /* STP_USE_DWARF_UNWINDER */" << endl; + + c->output << ".unwind_hdr = NULL, " << endl; + c->output << ".unwind_hdr_len = 0, " << endl; + c->output << ".unwind_is_ehframe = 0, " << endl; + c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ", " << endl; c->output << ".num_sections = sizeof(_stp_module_" << stpmod_idx << "_sections)/" << "sizeof(struct _stp_section), " << endl; |