diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-07-17 06:42:45 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-07-17 06:42:45 -0400 |
commit | 7795c7e74987876f71fe85ab9119b8810e8897f0 (patch) | |
tree | 44761281ec3f8752b3adc055448945ef600e880c /translate.cxx | |
parent | 4464a6bb1793076b3fa85a25c5a489cd9ef7d367 (diff) | |
download | systemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.tar.gz systemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.tar.xz systemtap-steved-7795c7e74987876f71fe85ab9119b8810e8897f0.zip |
support multiple-relocatable-section modules such as hypothetical -ffunction-sections .ko's
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/translate.cxx b/translate.cxx index 90d5536c..c69dc201 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4344,7 +4344,7 @@ dump_unwindsyms (Dwfl_Module *m, { unwindsym_dump_context* c = (unwindsym_dump_context*) arg; assert (c); - unsigned real_stpmodules_index = c->stp_module_index; + unsigned stpmod_idx = c->stp_module_index; string modname = name; @@ -4356,14 +4356,16 @@ dump_unwindsyms (Dwfl_Module *m, if (c->session.verbose > 1) clog << "dump_unwindsyms " << name - << " index=" << real_stpmodules_index + << " index=" << stpmod_idx << " base=0x" << hex << base << dec << endl; // We want to extract several bits of information: + // // - parts of the program-header that map the file's physical offsets to the text section // - section table: just a list of section (relocation) base addresses - // - symbol table of the text section, with all addresses relativized to .text base + // - symbol table of the text-like sections, with all addresses relativized to each base // - the contents of .debug_frame section, for unwinding purposes + // // In the future, we'll also care about data symbols. int syments = dwfl_module_getsymtab(m); @@ -4374,22 +4376,16 @@ dump_unwindsyms (Dwfl_Module *m, dwfl_assert ("dwfl_module_relocations", n >= 0); - c->output << "struct _stp_symbol _stp_module_" << real_stpmodules_index<< "_sections[] = {" << endl; - if (n > 0 && modname != "kernel") - c->output << " { 0, \".text\" }, " << endl; // XXX - else if (n >= 0 && modname == "kernel") - c->output << " { 0, \"_stext\" }, " << endl; - c->output << "};" << endl; - // XXX: unfortunate duplication with tapsets.cxx:emit_address() typedef map<Dwarf_Addr,const char*> addrmap_t; // NB: plain map, sorted by address - addrmap_t addrmap; // NB: plain map, sorted by address - + vector<string> seclist; // encountered relocation bases (section names) + map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap + Dwarf_Addr extra_offset = 0; - for (int i = 1; i < syments; ++i) + for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i) { GElf_Sym sym; const char *name = dwfl_module_getsym(m, i, &sym, NULL); @@ -4423,52 +4419,69 @@ dump_unwindsyms (Dwfl_Module *m, if (n == 1 && modname == "kernel" && secname && secname[0] == '\0') { // This is a symbol within a relocatable kernel image. - secname = "_stext"; // not actually used + secname = "_stext"; // NB: don't subtract session.sym_stext, which could be inconveniently NULL. + // Instead, sym_addr will get compensated later via extra_offset. } - else if (n > 0 && strcmp (secname, ".text")) /* XXX: only care about .text-related relocations for now. */ + else if (n > 0) { - if (c->session.verbose > 2) - clog << "Skipped symbol " << name << ", due to non-.text relocation section " << secname << endl; - continue; + assert (secname != NULL); + // secname adequately set } - else if (n == 0) + else { + assert (n == 0); // sym_addr is absolute, as it must be since there are no relocation bases + secname = ".absolute"; // sentinel } - else - { - // sym_addr has already been relocated relative to .text - } - addrmap[sym_addr] = name; + // Compute our section number + unsigned secidx; + for (secidx=0; secidx<seclist.size(); secidx++) + if (seclist[secidx]==secname) break; + + if (secidx == seclist.size()) // new section name + seclist.push_back (secname); + + (addrmap[secidx])[sym_addr] = name; } } } - // We write out a *sorted* symbol table, so the runtime doesn't have to sort them later. - c->output << "struct _stp_symbol _stp_module_" << real_stpmodules_index<< "_symbols[] = {" << endl; - for (addrmap_t::iterator it = addrmap.begin(); it != addrmap.end(); it++) + for (unsigned secidx = 0; secidx < seclist.size(); secidx++) { - if (it->first < extra_offset) - continue; // skip symbols that occur before our chosen base address + c->output << "struct _stp_symbol " + << "_stp_module_" << stpmod_idx<< "_symbols_" << secidx << "[] = {" << endl; - c->output << " { 0x" << hex << it->first-extra_offset << dec - << ", " << lex_cast_qstring (it->second) << " }," << endl; + // We write out a *sorted* symbol table, so the runtime doesn't have to sort them later. + for (addrmap_t::iterator it = addrmap[secidx].begin(); it != addrmap[secidx].end(); it++) + { + if (it->first < extra_offset) + continue; // skip symbols that occur before our chosen base address + + c->output << " { 0x" << hex << it->first-extra_offset << dec + << ", " << lex_cast_qstring (it->second) << " }," << endl; + } + c->output << "};" << endl; + } + + c->output << "struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {" << endl; + for (unsigned secidx = 0; secidx < seclist.size(); secidx++) + { + c->output << "{" << endl + << ".name = " << lex_cast_qstring(seclist[secidx]) << "," << endl + << ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << "," << endl + << ".num_symbols = sizeof(_stp_module_" << stpmod_idx << "_symbols_" << secidx << ")/sizeof(struct _stp_symbol)" << endl + << "}," << endl; } c->output << "};" << endl; - c->output << "struct _stp_module _stp_module_" << real_stpmodules_index << " = {" << endl; + c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl; c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl; - - c->output << ".sections = _stp_module_" << real_stpmodules_index << "_sections" << ", " << endl; - c->output << ".num_sections = sizeof(_stp_module_" << real_stpmodules_index << "_sections)/" - << "sizeof(struct _stp_symbol), " << 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; - c->output << ".symbols = _stp_module_" << real_stpmodules_index << "_symbols" << ", " << endl; - c->output << ".num_symbols = sizeof(_stp_module_" << real_stpmodules_index << "_symbols)/" - << "sizeof(struct _stp_symbol), " << endl; - c->output << "};" << endl << endl; c->undone_unwindsym_modules.erase (modname); @@ -4552,7 +4565,7 @@ emit_symbol_data (systemtap_session& s) dwfl_report_begin (dwfl); Dwfl_Module* mod = dwfl_report_offline (dwfl, modname.c_str(), modname.c_str(), -1); dwfl_report_end (dwfl, NULL, NULL); - if (mod != 0) // tolerate missing data; will inform user + if (mod != 0) // tolerate missing data; will warn below { ptrdiff_t off = 0; do @@ -4575,7 +4588,7 @@ emit_symbol_data (systemtap_session& s) kallsyms_out << "& _stp_module_" << i << "," << endl; } kallsyms_out << "};" << endl; - kallsyms_out << "int _stp_num_modules = " << ctx.stp_module_index << ";" << endl; + kallsyms_out << "unsigned _stp_num_modules = " << ctx.stp_module_index << ";" << endl; // Some nonexistent modules may have been identified with "-d". Note them. for (set<string>::iterator it = ctx.undone_unwindsym_modules.begin(); |