cc: Dynamically allocate memory for library path
authorPaul Chaignon <paul.chaignon@gmail.com>
Sun, 15 Jan 2017 09:11:42 +0000 (10:11 +0100)
committerPaul Chaignon <paul.chaignon@gmail.com>
Sun, 15 Jan 2017 11:16:57 +0000 (12:16 +0100)
src/cc/bcc_proc.c
src/cc/bcc_proc.h
src/cc/bcc_syms.cc
src/cc/usdt.cc
src/lua/bcc/libbcc.lua
src/lua/bcc/sym.lua
src/python/bcc/__init__.py
src/python/bcc/libbcc.py
tests/cc/test_c_api.cc

index 99b24b6..0d93d54 100644 (file)
@@ -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);
+}
index e7607f9..7b8bca9 100644 (file)
@@ -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
 }
index 2dc575b..ddbb5b9 100644 (file)
@@ -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);
   }
index 095e1ce..cd619dd 100644 (file)
@@ -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;
index 1f4cf4e..d744a46 100644 (file)
@@ -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);
index 023e4f3..39fe017 100644 (file)
@@ -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 }
index 2f484ab..a45bf47 100644 (file)
@@ -562,13 +562,20 @@ class BPF(object):
                 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):
index 2ba9867..4b15849 100644 (file)
@@ -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 = [
index 276301b..8d7a51f 100644 (file)
 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) {