Skip to content

Commit

Permalink
ProcSyms: fix off-by-ones, use binary search to resolve addresses (io…
Browse files Browse the repository at this point in the history
…visor#594)

* libbcc: fix off-by-one errors in resolving adjacent modules/symbols, add test

* libbcc: use binary search in ProcSyms::Module::find_addr()
  • Loading branch information
markdrayton authored and 4ast committed Jul 1, 2016
1 parent e51985e commit ab78817
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/cc/bcc_perf_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int bcc_perf_map_foreach_sym(const char *path, bcc_perf_map_symcb callback,
if (newline)
newline[0] = '\0';

callback(cursor, begin, len - 1, 0, payload);
callback(cursor, begin, len, 0, payload);
}

free(line);
Expand Down
22 changes: 15 additions & 7 deletions src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym) {
sym->offset = 0x0;

for (Module &mod : modules_) {
if (addr >= mod.start_ && addr <= mod.end_)
if (addr >= mod.start_ && addr < mod.end_)
return mod.find_addr(addr, sym);
}
return false;
Expand Down Expand Up @@ -152,6 +152,8 @@ void ProcSyms::Module::load_sym_table() {
bcc_perf_map_foreach_sym(name_.c_str(), _add_symbol, this);
else
bcc_elf_foreach_sym(name_.c_str(), _add_symbol, this);

std::sort(syms_.begin(), syms_.end());
}

bool ProcSyms::Module::find_name(const char *symname, uint64_t *addr) {
Expand All @@ -174,13 +176,19 @@ bool ProcSyms::Module::find_addr(uint64_t addr, struct bcc_symbol *sym) {
sym->module = name_.c_str();
sym->offset = offset;

for (Symbol &s : syms_) {
if (offset >= s.start && offset <= (s.start + s.size)) {
sym->name = s.name.c_str();
sym->offset = (offset - s.start);
return true;
}
auto it = std::upper_bound(syms_.begin(), syms_.end(), Symbol("", offset, 0));
if (it != syms_.begin())
--it;
else
it = syms_.end();

if (it != syms_.end()
&& offset >= it->start && offset < it->start + it->size) {
sym->name = it->name.c_str();
sym->offset = (offset - it->start);
return true;
}

return false;
}

Expand Down
4 changes: 4 additions & 0 deletions src/cc/syms.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class ProcSyms : SymbolCache {
uint64_t start;
uint64_t size;
int flags;

bool operator<(const struct Symbol& rhs) const {
return start < rhs.start;
}
};

struct Module {
Expand Down
7 changes: 7 additions & 0 deletions tests/cc/test_c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ static int child_func(void *arg) {
return -1;
}
fprintf(file, "%llx 10 dummy_fn\n", map_addr);
fprintf(file, "%llx 10 right_next_door_fn\n", map_addr + 0x10);
fclose(file);

sleep(5);
Expand Down Expand Up @@ -172,6 +173,12 @@ TEST_CASE("resolve symbols using /tmp/perf-pid.map", "[c_api]") {
REQUIRE(sym.module);
REQUIRE(string(sym.module) == perf_map_path(child));
REQUIRE(string("dummy_fn") == sym.name);

REQUIRE(bcc_symcache_resolve(resolver, (unsigned long long)map_addr + 0x10,
&sym) == 0);
REQUIRE(sym.module);
REQUIRE(string(sym.module) == perf_map_path(child));
REQUIRE(string("right_next_door_fn") == sym.name);
}

SECTION("separate namespace") {
Expand Down

0 comments on commit ab78817

Please sign in to comment.