Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 39 additions & 17 deletions src/cc/bcc_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,37 +929,59 @@ int bcc_elf_foreach_sym_lazy(const char *path, bcc_elf_symcb_lazy callback,
return foreach_sym_core(path, NULL, callback, o, payload);
}

int bcc_elf_get_text_scn_info(const char *path, uint64_t *addr,
uint64_t *offset) {
int err;
Elf_Scn *section = NULL;
GElf_Shdr header;
size_t stridx;
char *name;
int bcc_elf_get_scn_info(const char *path, uint64_t segment_offset,
uint64_t *addr, uint64_t *offset) {
int ret;
struct bcc_elf_file elf_file;
Elf_Scn *section = NULL;
GElf_Shdr shdr;
uint64_t segment_vaddr = 0, segment_memsz = 0;
int found_segment = 0;

bcc_elf_file_init(&elf_file);

if ((err = bcc_elf_file_open(path, &elf_file)) < 0 ||
(err = elf_getshdrstrndx(elf_file.elf, &stridx)) < 0)
if ((ret = bcc_elf_file_open(path, &elf_file)) < 0)
goto exit;

ret = -1;

size_t phdr_num, i;
if (elf_getphdrnum(elf_file.elf, &phdr_num) != 0)
goto exit;

GElf_Phdr phdr;
for (i = 0; i < phdr_num; ++i) {
if (!gelf_getphdr(elf_file.elf, i, &phdr))
continue;
if (phdr.p_type != PT_LOAD || !(phdr.p_flags & PF_X))
continue;

if (phdr.p_offset == segment_offset) {
segment_vaddr = phdr.p_vaddr;
segment_memsz = phdr.p_memsz;
found_segment = 1;
break;
}
}
if (!found_segment)
goto exit;

err = -1;
while ((section = elf_nextscn(elf_file.elf, section)) != 0) {
if (!gelf_getshdr(section, &header))
if (!gelf_getshdr(section, &shdr))
continue;

name = elf_strptr(elf_file.elf, stridx, header.sh_name);
if (name && !strcmp(name, ".text")) {
*addr = (uint64_t)header.sh_addr;
*offset = (uint64_t)header.sh_offset;
err = 0;
if (shdr.sh_addr >= segment_vaddr &&
shdr.sh_addr < segment_vaddr + segment_memsz) {
*addr = (uint64_t)shdr.sh_addr;
*offset = (uint64_t)shdr.sh_offset;
ret = 0;
break;
}
}

exit:
bcc_elf_file_close(&elf_file);
return err;
return ret;
}

int bcc_elf_foreach_load_section(const char *path,
Expand Down
4 changes: 2 additions & 2 deletions src/cc/bcc_elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ int bcc_elf_foreach_sym_lazy(const char *path, bcc_elf_symcb_lazy callback,
// 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_scn_info(const char *path, uint64_t segment_offset,
uint64_t *addr, uint64_t *offset);

int bcc_elf_get_type(const char *path);
int bcc_elf_is_pie(const char *path);
Expand Down
40 changes: 20 additions & 20 deletions src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,6 @@ int ProcSyms::_add_module(mod_info *mod, int enter_ns, void *payload) {
auto module = Module(
mod->name, modpath, &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(modpath->path(), &module.elf_so_addr_,
&module.elf_so_offset_) < 0) {
fprintf(stderr, "WARNING: Couldn't find .text section in %s\n",
modpath->alt_path());
fprintf(stderr, "WARNING: BCC can't handle sym look ups for %s",
modpath->alt_path());
}
}

if (!bcc_is_perf_map(modpath->path()) ||
module.type_ != ModuleType::UNKNOWN)
// Always add the module even if we can't read it, so that we could
Expand All @@ -226,7 +213,24 @@ int ProcSyms::_add_module(mod_info *mod, int enter_ns, void *payload) {
else
return 0;
}
it->ranges_.emplace_back(mod->start_addr, mod->end_addr, mod->file_offset);
// 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.
// since there will be different real offset, so we must calculate each time.
uint64_t elf_so_offset;
uint64_t elf_so_addr;
if (it->type_ == ModuleType::SO) {
if (bcc_elf_get_scn_info(modpath->path(), static_cast<uint64_t>(mod->file_offset),
&elf_so_addr, &elf_so_offset) < 0) {
fprintf(stderr, "WARNING: Couldn't find .text section in %s\n",
modpath->alt_path());
fprintf(stderr, "WARNING: BCC can't handle sym look ups for %s",
modpath->alt_path());
}
}

it->ranges_.emplace_back(mod->start_addr, mod->end_addr, mod->file_offset,
elf_so_addr, elf_so_offset);
// perf-PID map is added last. We try both inside the Process's mount
// namespace + chroot, and in global /tmp. Make sure we only add one.
if (it->type_ == ModuleType::PERF_MAP)
Expand Down Expand Up @@ -310,10 +314,6 @@ ProcSyms::Module::Module(const char *name, std::shared_ptr<ModulePath> path,
type_ = ModuleType::PERF_MAP;
else if (bcc_elf_is_vdso(path_->path()) == 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,
Expand Down Expand Up @@ -361,7 +361,7 @@ bool ProcSyms::Module::contains(uint64_t addr, uint64_t &offset) const {
if (addr >= range.start && addr < range.end) {
if (type_ == ModuleType::SO || type_ == ModuleType::VDSO) {
offset = __so_calc_mod_offset(range.start, range.file_offset,
elf_so_addr_, elf_so_offset_, addr);
range.elf_so_addr, range.elf_so_offset, addr);
} else {
offset = addr;
}
Expand Down Expand Up @@ -721,7 +721,7 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
mod.start == 0x0)
return -1;

if (bcc_elf_get_text_scn_info(module, &elf_so_addr, &elf_so_offset) < 0)
if (bcc_elf_get_scn_info(module, mod.file_offset, &elf_so_addr, &elf_so_offset) < 0)
return -1;

*global = __so_calc_global_addr(mod.start, mod.file_offset, elf_so_addr,
Expand Down
10 changes: 4 additions & 6 deletions src/cc/syms.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,10 @@ class ProcSyms : SymbolCache {
uint64_t start;
uint64_t end;
uint64_t file_offset;
Range(uint64_t s, uint64_t e, uint64_t f)
: start(s), end(e), file_offset(f) {}
uint64_t elf_so_addr;
uint64_t elf_so_offset;
Range(uint64_t s, uint64_t e, uint64_t f, uint64_t elf_so_addr, uint64_t elf_so_offset)
: start(s), end(e), file_offset(f), elf_so_addr(elf_so_addr), elf_so_offset(elf_so_offset) {}
};

Module(const char *name, std::shared_ptr<ModulePath> path,
Expand All @@ -168,10 +170,6 @@ 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_;

Expand Down