From 81654bf738f3b01ed4d2bd58f6b8093f8dea6c07 Mon Sep 17 00:00:00 2001 From: Paul Chaignon Date: Sun, 15 Jan 2017 10:11:42 +0100 Subject: [PATCH] cc: Dynamically allocate memory for library path --- src/cc/bcc_proc.c | 21 ++++++++++++--------- src/cc/bcc_proc.h | 3 ++- src/cc/bcc_syms.cc | 2 +- src/cc/usdt.cc | 3 ++- src/lua/bcc/libbcc.lua | 1 + src/lua/bcc/sym.lua | 9 +++++++-- src/python/bcc/__init__.py | 11 +++++++++-- src/python/bcc/libbcc.py | 6 ++++-- tests/cc/test_c_api.cc | 8 ++++++-- 9 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/cc/bcc_proc.c b/src/cc/bcc_proc.c index 99b24b6f67f0..0d93d548ca4f 100644 --- a/src/cc/bcc_proc.c +++ b/src/cc/bcc_proc.c @@ -197,8 +197,6 @@ static struct ld_lib { int flags; } * lib_cache; -static char libpath[4096]; - static int read_cache1(const char *ld_map) { struct ld_cache1 *ldcache = (struct ld_cache1 *)ld_map; const char *ldstrings = @@ -310,7 +308,7 @@ static bool match_so_flags(int flags) { return true; } -static bool which_so_in_process(const char* libname, int pid) { +static bool which_so_in_process(const char* libname, int pid, char* libpath) { int ret, found = false; char endline[4096], *mapname = NULL, *newline; char mappings_file[128]; @@ -341,7 +339,7 @@ static bool which_so_in_process(const char* libname, int pid) { if (strstr(mapname, ".so") && (strstr(mapname, search1) || strstr(mapname, search2))) { found = true; - memcpy(libpath, mapname, strlen(mapname)); + memcpy(libpath, mapname, strlen(mapname) + 1); break; } } while (ret != EOF); @@ -350,16 +348,17 @@ static bool which_so_in_process(const char* libname, int pid) { return found; } -const char *bcc_procutils_which_so(const char *libname, int pid) { +char *bcc_procutils_which_so(const char *libname, int pid) { const size_t soname_len = strlen(libname) + strlen("lib.so"); char soname[soname_len + 1]; + char libpath[4096]; int i; if (strchr(libname, '/')) - return libname; + return strdup(libname); - if (pid && which_so_in_process(libname, pid)) - return libpath; + if (pid && which_so_in_process(libname, pid, libpath)) + return strdup(libpath); if (lib_cache_count < 0) return NULL; @@ -374,8 +373,12 @@ const char *bcc_procutils_which_so(const char *libname, int pid) { for (i = 0; i < lib_cache_count; ++i) { if (!strncmp(lib_cache[i].libname, soname, soname_len) && match_so_flags(lib_cache[i].flags)) { - return lib_cache[i].path; + return strdup(lib_cache[i].path); } } return NULL; } + +void bcc_procutils_free(const char *ptr) { + free((void *)ptr); +} diff --git a/src/cc/bcc_proc.h b/src/cc/bcc_proc.h index e7607f9783a5..7b8bca91b10a 100644 --- a/src/cc/bcc_proc.h +++ b/src/cc/bcc_proc.h @@ -27,11 +27,12 @@ extern "C" { typedef int (*bcc_procutils_modulecb)(const char *, uint64_t, uint64_t, void *); typedef void (*bcc_procutils_ksymcb)(const char *, uint64_t, void *); -const char *bcc_procutils_which_so(const char *libname, int pid); +char *bcc_procutils_which_so(const char *libname, int pid); char *bcc_procutils_which(const char *binpath); int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *payload); int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload); +void bcc_procutils_free(const char *ptr); #ifdef __cplusplus } diff --git a/src/cc/bcc_syms.cc b/src/cc/bcc_syms.cc index 2dc575bad1e1..ddbb5b93c8e3 100644 --- a/src/cc/bcc_syms.cc +++ b/src/cc/bcc_syms.cc @@ -315,7 +315,7 @@ int bcc_resolve_symname(const char *module, const char *symname, return -1; if (strchr(module, '/')) { - sym->module = module; + sym->module = strdup(module); } else { sym->module = bcc_procutils_which_so(module, pid); } diff --git a/src/cc/usdt.cc b/src/cc/usdt.cc index 095e1ce192e5..cd619dd90fda 100644 --- a/src/cc/usdt.cc +++ b/src/cc/usdt.cc @@ -223,8 +223,9 @@ std::string Context::resolve_bin_path(const std::string &bin_path) { if (char *which = bcc_procutils_which(bin_path.c_str())) { result = which; ::free(which); - } else if (const char *which_so = bcc_procutils_which_so(bin_path.c_str(), 0)) { + } else if (char *which_so = bcc_procutils_which_so(bin_path.c_str(), 0)) { result = which_so; + ::free(which_so); } return result; diff --git a/src/lua/bcc/libbcc.lua b/src/lua/bcc/libbcc.lua index 1f4cf4efea83..d744a4690b7b 100644 --- a/src/lua/bcc/libbcc.lua +++ b/src/lua/bcc/libbcc.lua @@ -110,6 +110,7 @@ struct bcc_symbol { int bcc_resolve_symname(const char *module, const char *symname, const uint64_t addr, int pid, struct bcc_symbol *sym); +void bcc_procutils_free(const char *ptr); void *bcc_symcache_new(int pid); int bcc_symcache_resolve(void *symcache, uint64_t addr, struct bcc_symbol *sym); void bcc_symcache_refresh(void *resolver); diff --git a/src/lua/bcc/sym.lua b/src/lua/bcc/sym.lua index 023e4f3b2731..39fe017601d0 100644 --- a/src/lua/bcc/sym.lua +++ b/src/lua/bcc/sym.lua @@ -32,15 +32,20 @@ end local function check_path_symbol(module, symname, addr) local sym = SYM() + local module_path if libbcc.bcc_resolve_symname(module, symname, addr or 0x0, 0, sym) < 0 then if sym[0].module == nil then error("could not find library '%s' in the library path" % module) else + module_path = ffi.string(sym[0].module) + libbcc.bcc_procutils_free(sym[0].module) error("failed to resolve symbol '%s' in '%s'" % { - symname, ffi.string(sym[0].module)}) + symname, module_path}) end end - return ffi.string(sym[0].module), sym[0].offset + module_path = ffi.string(sym[0].module) + libbcc.bcc_procutils_free(sym[0].module) + return module_path, sym[0].offset end return { create_cache=create_cache, check_path_symbol=check_path_symbol } diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py index 2f484ab5c1eb..a45bf47bc97d 100644 --- a/src/python/bcc/__init__.py +++ b/src/python/bcc/__init__.py @@ -562,13 +562,20 @@ def _check_path_symbol(cls, module, symname, addr, pid): symname.encode("ascii"), addr or 0x0, c_pid, psym) < 0: if not sym.module: raise Exception("could not find library %s" % module) + lib.bcc_procutils_free(sym.module) raise Exception("could not determine address of symbol %s" % symname) - return sym.module.decode(), sym.offset + module_path = ct.cast(sym.module, ct.c_char_p).value.decode() + lib.bcc_procutils_free(sym.module) + return module_path, sym.offset @staticmethod def find_library(libname): res = lib.bcc_procutils_which_so(libname.encode("ascii"), 0) - return res if res is None else res.decode() + if not res: + return None + libpath = ct.cast(res, ct.c_char_p).value.decode() + lib.bcc_procutils_free(res) + return libpath @staticmethod def get_tracepoints(tp_re): diff --git a/src/python/bcc/libbcc.py b/src/python/bcc/libbcc.py index 2ba98671ce28..4b158492bf20 100644 --- a/src/python/bcc/libbcc.py +++ b/src/python/bcc/libbcc.py @@ -126,12 +126,14 @@ class bcc_symbol(ct.Structure): _fields_ = [ ('name', ct.c_char_p), ('demangle_name', ct.c_char_p), - ('module', ct.c_char_p), + ('module', ct.POINTER(ct.c_char)), ('offset', ct.c_ulonglong), ] -lib.bcc_procutils_which_so.restype = ct.c_char_p +lib.bcc_procutils_which_so.restype = ct.POINTER(ct.c_char) lib.bcc_procutils_which_so.argtypes = [ct.c_char_p, ct.c_int] +lib.bcc_procutils_free.restype = None +lib.bcc_procutils_free.argtypes = [ct.c_void_p] lib.bcc_resolve_symname.restype = ct.c_int lib.bcc_resolve_symname.argtypes = [ diff --git a/tests/cc/test_c_api.cc b/tests/cc/test_c_api.cc index 276301bedd1e..8d7a51fe3b5f 100644 --- a/tests/cc/test_c_api.cc +++ b/tests/cc/test_c_api.cc @@ -30,17 +30,19 @@ using namespace std; TEST_CASE("shared object resolution", "[c_api]") { - const char *libm = bcc_procutils_which_so("m", 0); + char *libm = bcc_procutils_which_so("m", 0); REQUIRE(libm); REQUIRE(libm[0] == '/'); REQUIRE(string(libm).find("libm.so") != string::npos); + free(libm); } TEST_CASE("shared object resolution using loaded libraries", "[c_api]") { - const char *libelf = bcc_procutils_which_so("elf", getpid()); + char *libelf = bcc_procutils_which_so("elf", getpid()); REQUIRE(libelf); REQUIRE(libelf[0] == '/'); REQUIRE(string(libelf).find("libelf") != string::npos); + free(libelf); } TEST_CASE("binary resolution with `which`", "[c_api]") { @@ -68,6 +70,7 @@ TEST_CASE("resolve symbol name in external library", "[c_api]") { REQUIRE(string(sym.module).find("libc.so") != string::npos); REQUIRE(sym.module[0] == '/'); REQUIRE(sym.offset != 0); + bcc_procutils_free(sym.module); } TEST_CASE("resolve symbol name in external library using loaded libraries", "[c_api]") { @@ -77,6 +80,7 @@ TEST_CASE("resolve symbol name in external library using loaded libraries", "[c_ REQUIRE(string(sym.module).find("libbcc.so") != string::npos); REQUIRE(sym.module[0] == '/'); REQUIRE(sym.offset != 0); + bcc_procutils_free(sym.module); } extern "C" int _a_test_function(const char *a_string) {