Commit aff6ce70 authored by Teng Qin's avatar Teng Qin

Use bcc_symbol_option in bcc_resolve_symname

This commit makes `bcc_resolve_symname` to take an `bcc_symbol_option`
parameter, and pass it to underlying calls to control symboling behavior.
When `NULL` is passed, it will fallback to default which is current
behavior that uses debug file, verify debug file CRC, and check all
types of symbols.

This commit also removes the unneccesary intermediate
`bcc_find_symbol_addr`.

Added documentation for usage of the API, updated most call sites to use
default with `NULL`, and fixed some memory leaks at call sites.
parent 36e7d545
...@@ -469,8 +469,9 @@ StatusTuple BPF::unload_func(const std::string& func_name) { ...@@ -469,8 +469,9 @@ StatusTuple BPF::unload_func(const std::string& func_name) {
StatusTuple BPF::check_binary_symbol(const std::string& binary_path, StatusTuple BPF::check_binary_symbol(const std::string& binary_path,
const std::string& symbol, const std::string& symbol,
uint64_t symbol_addr, bcc_symbol* output) { uint64_t symbol_addr, bcc_symbol* output) {
// TODO: Fix output.module memory leak here
int res = bcc_resolve_symname(binary_path.c_str(), symbol.c_str(), int res = bcc_resolve_symname(binary_path.c_str(), symbol.c_str(),
symbol_addr, 0, output); symbol_addr, 0, nullptr, output);
if (res < 0) if (res < 0)
return StatusTuple( return StatusTuple(
-1, "Unable to find offset for binary %s symbol %s address %lx", -1, "Unable to find offset for binary %s symbol %s address %lx",
......
...@@ -438,21 +438,6 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address, ...@@ -438,21 +438,6 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
return 0; return 0;
} }
static int _find_sym(const char *symname, uint64_t addr, uint64_t end,
int flags, void *payload) {
struct bcc_symbol *sym = (struct bcc_symbol *)payload;
// TODO: check for actual function symbol in flags
if (!strcmp(sym->name, symname)) {
sym->offset = addr;
return -1;
}
return 0;
}
int bcc_find_symbol_addr(struct bcc_symbol *sym) {
return bcc_elf_foreach_sym(sym->module, _find_sym, sym);
}
static int _sym_cb_wrapper(const char *symname, uint64_t addr, uint64_t end, static int _sym_cb_wrapper(const char *symname, uint64_t addr, uint64_t end,
int flags, void *payload) { int flags, void *payload) {
SYM_CB cb = (SYM_CB) payload; SYM_CB cb = (SYM_CB) payload;
...@@ -473,17 +458,32 @@ int bcc_foreach_function_symbol(const char *module, SYM_CB cb) { ...@@ -473,17 +458,32 @@ int bcc_foreach_function_symbol(const char *module, SYM_CB cb) {
module, _sym_cb_wrapper, &default_option, (void *)cb); module, _sym_cb_wrapper, &default_option, (void *)cb);
} }
static int _find_sym(const char *symname, uint64_t addr, uint64_t end,
int flags, void *payload) {
struct bcc_symbol *sym = (struct bcc_symbol *)payload;
if (!strcmp(sym->name, symname)) {
sym->offset = addr;
return -1;
}
return 0;
}
int bcc_resolve_symname(const char *module, const char *symname, int bcc_resolve_symname(const char *module, const char *symname,
const uint64_t addr, int pid, struct bcc_symbol *sym) { const uint64_t addr, int pid,
struct bcc_symbol_option *option,
struct bcc_symbol *sym) {
uint64_t load_addr; uint64_t load_addr;
static struct bcc_symbol_option default_option = {
sym->module = NULL; .use_debug_file = 1,
sym->name = NULL; .check_debug_file_crc = 1,
sym->offset = 0x0; .use_symbol_type = BCC_SYM_ALL_TYPES,
};
if (module == NULL) if (module == NULL)
return -1; return -1;
memset(sym, 0, sizeof(bcc_symbol));
if (strchr(module, '/')) { if (strchr(module, '/')) {
sym->module = strdup(module); sym->module = strdup(module);
} else { } else {
...@@ -501,8 +501,11 @@ int bcc_resolve_symname(const char *module, const char *symname, ...@@ -501,8 +501,11 @@ int bcc_resolve_symname(const char *module, const char *symname,
sym->name = symname; sym->name = symname;
sym->offset = addr; sym->offset = addr;
if (option == NULL)
option = &default_option;
if (sym->name && sym->offset == 0x0) if (sym->name && sym->offset == 0x0)
if (bcc_find_symbol_addr(sym) < 0) if (bcc_elf_foreach_sym(sym->module, _find_sym, option, sym) < 0)
goto invalid_module; goto invalid_module;
if (sym->offset == 0x0) if (sym->offset == 0x0)
......
...@@ -62,9 +62,22 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address, ...@@ -62,9 +62,22 @@ int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
// Will prefer use debug file and check debug file CRC when reading the module. // Will prefer use debug file and check debug file CRC when reading the module.
int bcc_foreach_function_symbol(const char *module, SYM_CB cb); int bcc_foreach_function_symbol(const char *module, SYM_CB cb);
int bcc_find_symbol_addr(struct bcc_symbol *sym); // Find the offset of a symbol in a module binary. If addr is not zero, will
// calculate the offset using the provided addr and the module's load address.
//
// If pid is provided, will use it to help lookup the module in the Process and
// enter the Process's mount Namespace.
//
// If option is not NULL, will respect the specified options for lookup.
// Otherwise default option will apply, which is to use debug file, verify
// checksum, and try all types of symbols.
//
// Return 0 on success and -1 on failure. Output will be write to sym. After
// use, sym->module need to be freed if it's not empty.
int bcc_resolve_symname(const char *module, const char *symname, int bcc_resolve_symname(const char *module, const char *symname,
const uint64_t addr, int pid, struct bcc_symbol *sym); const uint64_t addr, int pid,
struct bcc_symbol_option* option,
struct bcc_symbol *sym);
void *bcc_enter_mount_ns(int pid); void *bcc_enter_mount_ns(int pid);
void bcc_exit_mount_ns(void **guard); void bcc_exit_mount_ns(void **guard);
......
...@@ -40,9 +40,11 @@ bool Argument::get_global_address(uint64_t *address, const std::string &binpath, ...@@ -40,9 +40,11 @@ bool Argument::get_global_address(uint64_t *address, const std::string &binpath,
} }
if (!bcc_elf_is_shared_obj(binpath.c_str())) { if (!bcc_elf_is_shared_obj(binpath.c_str())) {
struct bcc_symbol sym = {deref_ident_->c_str(), binpath.c_str(), 0x0}; struct bcc_symbol sym;
if (!bcc_find_symbol_addr(&sym) && sym.offset) { if (bcc_resolve_symname(binpath.c_str(), deref_ident_->c_str(), 0x0, -1, nullptr, &sym) == 0) {
*address = sym.offset; *address = sym.offset;
if (sym.module)
::free(const_cast<char*>(sym.module));
return true; return true;
} }
} }
......
...@@ -121,7 +121,8 @@ struct bcc_symbol_option { ...@@ -121,7 +121,8 @@ struct bcc_symbol_option {
}; };
int bcc_resolve_symname(const char *module, const char *symname, const uint64_t addr, int bcc_resolve_symname(const char *module, const char *symname, const uint64_t addr,
int pid, struct bcc_symbol *sym); int pid, struct bcc_symbol_option *option,
struct bcc_symbol *sym);
void bcc_procutils_free(const char *ptr); void bcc_procutils_free(const char *ptr);
void *bcc_symcache_new(int pid); void *bcc_symcache_new(int pid);
void bcc_symbol_free_demangle_name(struct bcc_symbol *sym); void bcc_symbol_free_demangle_name(struct bcc_symbol *sym);
......
...@@ -35,7 +35,7 @@ end ...@@ -35,7 +35,7 @@ end
local function check_path_symbol(module, symname, addr, pid) local function check_path_symbol(module, symname, addr, pid)
local sym = SYM() local sym = SYM()
local module_path local module_path
if libbcc.bcc_resolve_symname(module, symname, addr or 0x0, pid or 0, sym) < 0 then if libbcc.bcc_resolve_symname(module, symname, addr or 0x0, pid or 0, nil, sym) < 0 then
if sym[0].module == nil then if sym[0].module == nil then
error("could not find library '%s' in the library path" % module) error("could not find library '%s' in the library path" % module)
else else
......
...@@ -24,7 +24,7 @@ import errno ...@@ -24,7 +24,7 @@ import errno
import sys import sys
basestring = (unicode if sys.version_info[0] < 3 else str) basestring = (unicode if sys.version_info[0] < 3 else str)
from .libbcc import lib, _CB_TYPE, bcc_symbol, _SYM_CB_TYPE from .libbcc import lib, _CB_TYPE, bcc_symbol, bcc_symbol_option, _SYM_CB_TYPE
from .table import Table from .table import Table
from .perf import Perf from .perf import Perf
from .utils import get_online_cpus from .utils import get_online_cpus
...@@ -607,11 +607,12 @@ class BPF(object): ...@@ -607,11 +607,12 @@ class BPF(object):
sym = bcc_symbol() sym = bcc_symbol()
psym = ct.pointer(sym) psym = ct.pointer(sym)
c_pid = 0 if pid == -1 else pid c_pid = 0 if pid == -1 else pid
if lib.bcc_resolve_symname(module.encode("ascii"), if lib.bcc_resolve_symname(
symname.encode("ascii"), addr or 0x0, c_pid, psym) < 0: module.encode("ascii"), symname.encode("ascii"),
if not sym.module: addr or 0x0, c_pid,
raise Exception("could not find library %s" % module) ct.cast(None, ct.POINTER(bcc_symbol_option)),
lib.bcc_procutils_free(sym.module) psym,
) < 0:
raise Exception("could not determine address of symbol %s" % symname) raise Exception("could not determine address of symbol %s" % symname)
module_path = ct.cast(sym.module, ct.c_char_p).value.decode() module_path = ct.cast(sym.module, ct.c_char_p).value.decode()
lib.bcc_procutils_free(sym.module) lib.bcc_procutils_free(sym.module)
......
...@@ -149,7 +149,7 @@ lib.bcc_procutils_language.argtypes = [ct.c_int] ...@@ -149,7 +149,7 @@ lib.bcc_procutils_language.argtypes = [ct.c_int]
lib.bcc_resolve_symname.restype = ct.c_int lib.bcc_resolve_symname.restype = ct.c_int
lib.bcc_resolve_symname.argtypes = [ lib.bcc_resolve_symname.argtypes = [
ct.c_char_p, ct.c_char_p, ct.c_ulonglong, ct.c_int, ct.POINTER(bcc_symbol)] ct.c_char_p, ct.c_char_p, ct.c_ulonglong, ct.c_int, ct.POINTER(bcc_symbol_option), ct.POINTER(bcc_symbol)]
_SYM_CB_TYPE = ct.CFUNCTYPE(ct.c_int, ct.c_char_p, ct.c_ulonglong) _SYM_CB_TYPE = ct.CFUNCTYPE(ct.c_int, ct.c_char_p, ct.c_ulonglong)
lib.bcc_foreach_function_symbol.restype = ct.c_int lib.bcc_foreach_function_symbol.restype = ct.c_int
......
...@@ -92,7 +92,7 @@ TEST_CASE("file-backed mapping identification") { ...@@ -92,7 +92,7 @@ TEST_CASE("file-backed mapping identification") {
TEST_CASE("resolve symbol name in external library", "[c_api]") { TEST_CASE("resolve symbol name in external library", "[c_api]") {
struct bcc_symbol sym; struct bcc_symbol sym;
REQUIRE(bcc_resolve_symname("c", "malloc", 0x0, 0, &sym) == 0); REQUIRE(bcc_resolve_symname("c", "malloc", 0x0, 0, nullptr, &sym) == 0);
REQUIRE(string(sym.module).find("libc.so") != string::npos); REQUIRE(string(sym.module).find("libc.so") != string::npos);
REQUIRE(sym.module[0] == '/'); REQUIRE(sym.module[0] == '/');
REQUIRE(sym.offset != 0); REQUIRE(sym.offset != 0);
...@@ -102,7 +102,7 @@ TEST_CASE("resolve symbol name in external library", "[c_api]") { ...@@ -102,7 +102,7 @@ TEST_CASE("resolve symbol name in external library", "[c_api]") {
TEST_CASE("resolve symbol name in external library using loaded libraries", "[c_api]") { TEST_CASE("resolve symbol name in external library using loaded libraries", "[c_api]") {
struct bcc_symbol sym; struct bcc_symbol sym;
REQUIRE(bcc_resolve_symname("bcc", "bcc_procutils_which", 0x0, getpid(), &sym) == 0); REQUIRE(bcc_resolve_symname("bcc", "bcc_procutils_which", 0x0, getpid(), nullptr, &sym) == 0);
REQUIRE(string(sym.module).find("libbcc.so") != string::npos); REQUIRE(string(sym.module).find("libbcc.so") != string::npos);
REQUIRE(sym.module[0] == '/'); REQUIRE(sym.module[0] == '/');
REQUIRE(sym.offset != 0); REQUIRE(sym.offset != 0);
......
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