summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-04-14 19:30:56 +0200
committerMark Wielaard <mjw@redhat.com>2009-04-14 19:30:56 +0200
commit60ad8ebae62f472a9f089f51053a2d0d66c67a95 (patch)
tree777c4ec2ff2754d6d2767d2bc82e801d37d43a44
parent412e8ec0dadbc0010c865f9a285a748b8d08c053 (diff)
downloadsystemtap-steved-60ad8ebae62f472a9f089f51053a2d0d66c67a95.tar.gz
systemtap-steved-60ad8ebae62f472a9f089f51053a2d0d66c67a95.tar.xz
systemtap-steved-60ad8ebae62f472a9f089f51053a2d0d66c67a95.zip
Keep track of relocation section sizes.
* runtime/sym.h (_stp_section): Add size field. * translate.cxx (dump_unwindsyms): Get start of module address space, turn seclist into vector of secname, size pairs, track relocation section size, or add module address range if no sections, output size in _stp_section list.
-rw-r--r--runtime/sym.h1
-rw-r--r--translate.cxx58
2 files changed, 44 insertions, 15 deletions
diff --git a/runtime/sym.h b/runtime/sym.h
index 586b10ca..80c334fb 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -18,6 +18,7 @@ struct _stp_symbol {
struct _stp_section {
const char *name;
unsigned long addr; /* XXX: belongs in per-address-space tables */
+ unsigned long size; /* length of the address space module covers. */
struct _stp_symbol *symbols; /* ordered by address */
unsigned num_symbols;
};
diff --git a/translate.cxx b/translate.cxx
index a22e9a5b..d81287ee 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4532,9 +4532,14 @@ dump_unwindsyms (Dwfl_Module *m,
}
}
- // Use end as sanity check when resolving symbol addresses.
- Dwarf_Addr end;
- dwfl_module_info (m, NULL, NULL, &end, NULL, NULL, NULL, NULL);
+ // Get the canonical path of the main file for comparison at runtime.
+ // When given directly by the user through -d or in case of the kernel
+ // name and path might differ. path should be used for matching.
+ // Use end as sanity check when resolving symbol addresses and to
+ // calculate size for .dynamic and .absolute sections.
+ const char *mainfile;
+ Dwarf_Addr start, end;
+ dwfl_module_info (m, NULL, &start, &end, NULL, NULL, &mainfile, NULL);
// Look up the relocation basis for symbols
int n = dwfl_module_relocations (m);
@@ -4545,7 +4550,8 @@ dump_unwindsyms (Dwfl_Module *m,
// XXX: unfortunate duplication with tapsets.cxx:emit_address()
typedef map<Dwarf_Addr,const char*> addrmap_t; // NB: plain map, sorted by address
- vector<string> seclist; // encountered relocation bases (section names)
+ vector<pair<string,unsigned> > seclist; // encountered relocation bases
+ // (section names and sizes)
map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap
Dwarf_Addr extra_offset = 0;
@@ -4588,11 +4594,11 @@ dump_unwindsyms (Dwfl_Module *m,
|| sym.st_value < base)) // before first section.
{
Dwarf_Addr sym_addr = sym.st_value;
+ Dwarf_Addr save_addr = sym_addr;
const char *secname = NULL;
if (n > 0) // only try to relocate if there exist relocation bases
{
- Dwarf_Addr save_addr = sym_addr;
int ki = dwfl_module_relocate_address (m, &sym_addr);
dwfl_assert ("dwfl_module_relocate_address", ki >= 0);
secname = dwfl_module_relocation_info (m, ki, NULL);
@@ -4645,10 +4651,31 @@ dump_unwindsyms (Dwfl_Module *m,
// Compute our section number
unsigned secidx;
for (secidx=0; secidx<seclist.size(); secidx++)
- if (seclist[secidx]==secname) break;
+ if (seclist[secidx].first==secname) break;
if (secidx == seclist.size()) // new section name
- seclist.push_back (secname);
+ {
+ // absolute, dynamic or kernel have just one relocation
+ // section, which covers the whole module address range.
+ unsigned size;
+ if (secidx == 0
+ && (n == 0
+ || (n == 1
+ && (strcmp(secname, ".dynamic") == 0
+ || strcmp(secname, "_stext") == 0))))
+ size = end - start;
+ else
+ {
+ Dwarf_Addr b;
+ Elf_Scn *scn;
+ GElf_Shdr *shdr, shdr_mem;
+ scn = dwfl_module_address_section (m, &save_addr, &b);
+ assert (scn != NULL);
+ shdr = gelf_getshdr(scn, &shdr_mem);
+ size = shdr->sh_size;
+ }
+ seclist.push_back (make_pair(secname,size));
+ }
(addrmap[secidx])[sym_addr] = name;
}
@@ -4709,12 +4736,17 @@ dump_unwindsyms (Dwfl_Module *m,
}
c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n";
+ // For the kernel, executables (ET_EXEC) or shared libraries (ET_DYN)
+ // there is just one section that covers the whole address space of
+ // the module. For kernel modules (ET_REL) there can be multiple
+ // sections that get relocated separately.
for (unsigned secidx = 0; secidx < seclist.size(); secidx++)
{
c->output << "{\n"
- << ".name = " << lex_cast_qstring(seclist[secidx]) << ",\n"
+ << ".name = " << lex_cast_qstring(seclist[secidx].first) << ",\n"
+ << ".size = 0x" << hex << seclist[secidx].second << dec << ",\n"
<< ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n"
- << ".num_symbols = sizeof(_stp_module_" << stpmod_idx << "_symbols_" << secidx << ")/sizeof(struct _stp_symbol)\n"
+ << ".num_symbols = " << addrmap[secidx].size() << "\n"
<< "},\n";
}
c->output << "};\n";
@@ -4722,11 +4754,6 @@ dump_unwindsyms (Dwfl_Module *m,
c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
c->output << ".name = " << lex_cast_qstring (modname) << ", \n";
- // Get the canonical path of the main file for comparison at runtime.
- // When given directly by the user through -d or in case of the kernel
- // name and path might differ. path should be used for matching.
- const char *mainfile;
- dwfl_module_info (m, NULL, NULL, NULL, NULL, NULL, &mainfile, NULL);
mainfile = canonicalize_file_name(mainfile);
c->output << ".path = " << lex_cast_qstring (mainfile) << ",\n";
@@ -4861,7 +4888,8 @@ emit_symbol_data (systemtap_session& s)
{
NULL, /* dwfl_linux_kernel_find_elf, */
dwfl_standard_find_debuginfo,
- dwfl_offline_section_address,
+ NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN.
+ dwfl_offline_section_address, */
(char **) & debuginfo_path
};