Commit 5d23500a authored by yonghong-song's avatar yonghong-song Committed by GitHub

Merge pull request #1670 from joelagnel/submit-fix-1628

bcc/syms: Fix shared library symbol lookup
parents cbb16114 5a1106c6
......@@ -500,6 +500,41 @@ int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback,
path, callback, (struct bcc_symbol_option*)option, payload, 0);
}
int bcc_elf_get_text_scn_info(const char *path, uint64_t *addr,
uint64_t *offset) {
Elf *e = NULL;
int fd = -1, err;
Elf_Scn *section = NULL;
GElf_Shdr header;
size_t stridx;
char *name;
if ((err = openelf(path, &e, &fd)) < 0 ||
(err = elf_getshdrstrndx(e, &stridx)) < 0)
goto exit;
err = -1;
while ((section = elf_nextscn(e, section)) != 0) {
if (!gelf_getshdr(section, &header))
continue;
name = elf_strptr(e, stridx, header.sh_name);
if (name && !strcmp(name, ".text")) {
*addr = (uint64_t)header.sh_addr;
*offset = (uint64_t)header.sh_offset;
err = 0;
break;
}
}
exit:
if (e)
elf_end(e);
if (fd >= 0)
close(fd);
return err;
}
int bcc_elf_foreach_load_section(const char *path,
bcc_elf_load_sectioncb callback,
void *payload) {
......
......@@ -61,6 +61,9 @@ int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback, void *option,
// Returns -1 on error, and 0 on success or stopped by callback
int bcc_elf_foreach_vdso_sym(bcc_elf_symcb callback, void *payload);
int bcc_elf_get_text_scn_info(const char *path, uint64_t *addr,
uint64_t *offset);
int bcc_elf_get_type(const char *path);
int bcc_elf_is_shared_obj(const char *path);
int bcc_elf_is_exe(const char *path);
......
......@@ -158,6 +158,18 @@ int ProcSyms::_add_module(const char *modname, uint64_t start, uint64_t end,
auto module = Module(
modname, check_mount_ns ? ps->mount_ns_instance_.get() : nullptr,
&ps->symbol_option_);
// pid/maps doesn't account for file_offset of text within the ELF.
// It only gives the mmap offset. We need the real offset for symbol
// lookup.
if (module.type_ == ModuleType::SO) {
if (bcc_elf_get_text_scn_info(modname, &module.elf_so_addr_,
&module.elf_so_offset_) < 0) {
fprintf(stderr, "WARNING: Couldn't find .text section in %s\n", modname);
fprintf(stderr, "WARNING: BCC can't handle sym look ups for %s", modname);
}
}
if (!bcc_is_perf_map(modname) || module.type_ != ModuleType::UNKNOWN)
// Always add the module even if we can't read it, so that we could
// report correct module name. Unless it's a perf map that we only
......@@ -251,6 +263,10 @@ ProcSyms::Module::Module(const char *name, ProcMountNS *mount_ns,
type_ = ModuleType::PERF_MAP;
else if (bcc_elf_is_vdso(name_.c_str()) == 1)
type_ = ModuleType::VDSO;
// Will be stored later
elf_so_offset_ = 0;
elf_so_addr_ = 0;
}
int ProcSyms::Module::_add_symbol(const char *symname, uint64_t start,
......@@ -282,13 +298,22 @@ void ProcSyms::Module::load_sym_table() {
}
bool ProcSyms::Module::contains(uint64_t addr, uint64_t &offset) const {
for (const auto &range : ranges_)
for (const auto &range : ranges_) {
if (addr >= range.start && addr < range.end) {
offset = (type_ == ModuleType::SO || type_ == ModuleType::VDSO)
? (addr - range.start + range.file_offset)
: addr;
if (type_ == ModuleType::SO || type_ == ModuleType::VDSO) {
// Offset within the mmap
offset = addr - range.start + range.file_offset;
// Offset within the ELF for SO symbol lookup
offset += (elf_so_addr_ - elf_so_offset_);
} else {
offset = addr;
}
return true;
}
}
return false;
}
......
......@@ -108,6 +108,10 @@ class ProcSyms : SymbolCache {
bcc_symbol_option *symbol_option_;
ModuleType type_;
// The file offset within the ELF of the SO's first text section.
uint64_t elf_so_offset_;
uint64_t elf_so_addr_;
std::unordered_set<std::string> symnames_;
std::vector<Symbol> syms_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment