summaryrefslogtreecommitdiffstats
path: root/translate.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'translate.cxx')
-rw-r--r--translate.cxx82
1 files changed, 82 insertions, 0 deletions
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;