diff options
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/translate.cxx b/translate.cxx index e5435fac..64308fe3 100644 --- a/translate.cxx +++ b/translate.cxx @@ -948,9 +948,9 @@ c_unparser::emit_common_header () } } - for (unsigned i=0; i<session->functions.size(); i++) + for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++) { - functiondecl* fd = session->functions[i]; + functiondecl* fd = it->second; o->newline() << "struct function_" << c_varname (fd->name) << "_locals {"; o->indent(1); @@ -1778,8 +1778,8 @@ c_unparser::emit_map_type_instantiations () for (unsigned i = 0; i < session->probes.size(); ++i) collect_map_index_types(session->probes[i]->locals, types); - for (unsigned i = 0; i < session->functions.size(); ++i) - collect_map_index_types(session->functions[i]->locals, types); + for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++) + collect_map_index_types(it->second->locals, types); if (!types.empty()) o->newline() << "#include \"alloc.c\""; @@ -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)), @@ -4431,7 +4468,7 @@ dump_unwindsyms (Dwfl_Module *m, else if (n > 0) { assert (secname != NULL); - // secname adequately set + // secname adequately set // NB: it may be an empty string for ET_DYN objects // like shared libraries, as their relocation base @@ -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,27 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl; c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl; + c->output << ".dwarf_module_base = 0x" << hex << base << dec << ", " << 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; @@ -4724,19 +4807,19 @@ translate_pass (systemtap_session& s) s.op->newline(-1) << "};"; s.op->assert_0_indent(); - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { if (pending_interrupts) return 1; s.op->newline(); - s.up->emit_functionsig (s.functions[i]); + s.up->emit_functionsig (it->second); } s.op->assert_0_indent(); - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { if (pending_interrupts) return 1; s.op->newline(); - s.up->emit_function (s.functions[i]); + s.up->emit_function (it->second); } s.op->assert_0_indent(); |