Add option to control bcc_elf_foreach_sym behavior
authorTeng Qin <qinteng@fb.com>
Thu, 4 May 2017 07:09:20 +0000 (00:09 -0700)
committerTeng Qin <qinteng@fb.com>
Sat, 20 May 2017 04:55:57 +0000 (21:55 -0700)
This commit adds a `bcc_symbol_option` to configure various symboling
behaviors. Currently added options for reading debug file, and what type
of symbols are wanted.

This commit also makes bcc_elf_foreach_sym take a `bcc_symbol_option`
parameter and repect the specified configurations.

src/cc/bcc_elf.c
src/cc/bcc_elf.h
src/cc/bcc_syms.h
src/lua/bcc/libbcc.lua
src/python/bcc/libbcc.py

index 8540a605faf43515da5d3b5febd66efc31541417..4b742eba006ee23176a941c87a127e0aea78825f 100644 (file)
 
 #include <gelf.h>
 #include "bcc_elf.h"
+#include "bcc_syms.h"
+
 #define NT_STAPSDT 3
+#define ELF_ST_TYPE(x) (((uint32_t) x) & 0xf)
 
 static int openelf(const char *path, Elf **elf_out, int *fd_out) {
   if (elf_version(EV_CURRENT) == EV_NONE)
@@ -150,6 +153,7 @@ int bcc_elf_foreach_usdt(const char *path, bcc_elf_probecb callback,
 }
 
 static int list_in_scn(Elf *e, Elf_Scn *section, size_t stridx, size_t symsize,
+                       struct bcc_symbol_option *option,
                        bcc_elf_symcb callback, void *payload) {
   Elf_Data *data = NULL;
 
@@ -168,6 +172,15 @@ static int list_in_scn(Elf *e, Elf_Scn *section, size_t stridx, size_t symsize,
 
       if ((name = elf_strptr(e, stridx, sym.st_name)) == NULL)
         continue;
+      if (name[0] == 0)
+        continue;
+
+      if (sym.st_value == 0)
+        continue;
+
+      uint32_t flag = 1 << ELF_ST_TYPE(sym.st_info);
+      if (!(option->use_symbol_type & flag))
+        continue;
 
       if (callback(name, sym.st_value, sym.st_size, sym.st_info, payload) < 0)
         return 1;      // signal termination to caller
@@ -177,7 +190,8 @@ static int list_in_scn(Elf *e, Elf_Scn *section, size_t stridx, size_t symsize,
   return 0;
 }
 
-static int listsymbols(Elf *e, bcc_elf_symcb callback, void *payload) {
+static int listsymbols(Elf *e, bcc_elf_symcb callback, void *payload,
+                       struct bcc_symbol_option *option) {
   Elf_Scn *section = NULL;
 
   while ((section = elf_nextscn(e, section)) != 0) {
@@ -190,7 +204,7 @@ static int listsymbols(Elf *e, bcc_elf_symcb callback, void *payload) {
       continue;
 
     int rc = list_in_scn(e, section, header.sh_link, header.sh_entsize,
-                         callback, payload);
+                         option, callback, payload);
     if (rc == 1)
       break;    // callback signaled termination
 
@@ -347,7 +361,8 @@ static int verify_checksum(const char *file, unsigned int crc) {
   return actual == crc;
 }
 
-static char *find_debug_via_debuglink(Elf *e, const char *binpath) {
+static char *find_debug_via_debuglink(Elf *e, const char *binpath,
+                                      int check_crc) {
   char fullpath[PATH_MAX];
   char *bindir = NULL;
   char *res = NULL;
@@ -386,9 +401,9 @@ static char *find_debug_via_debuglink(Elf *e, const char *binpath) {
 
 DONE:
   free(bindir);
-  if (verify_checksum(res, crc))
-    return res;
-  return NULL;
+  if (check_crc && !verify_checksum(res, crc))
+    return NULL;
+  return res;
 }
 
 static char *find_debug_via_buildid(Elf *e) {
@@ -412,11 +427,15 @@ static char *find_debug_via_buildid(Elf *e) {
 }
 
 static int foreach_sym_core(const char *path, bcc_elf_symcb callback,
-                            void *payload, int is_debug_file) {
+                            struct bcc_symbol_option *option, void *payload,
+                            int is_debug_file) {
   Elf *e;
   int fd, res;
   char *debug_file;
 
+  if (!option)
+    return -1;
+
   if (openelf(path, &e, &fd) < 0)
     return -1;
 
@@ -424,27 +443,29 @@ static int foreach_sym_core(const char *path, bcc_elf_symcb callback,
   // using the build-id section, then using the debuglink section. These are
   // also the rules that GDB folows.
   // See: https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
-  if (!is_debug_file) {
+  if (option->use_debug_file && !is_debug_file) {
     // The is_debug_file argument helps avoid infinitely resolving debuginfo
     // files for debuginfo files and so on.
     debug_file = find_debug_via_buildid(e);
     if (!debug_file)
-      debug_file = find_debug_via_debuglink(e, path);
+      debug_file = find_debug_via_debuglink(e, path,
+                                            option->check_debug_file_crc);
     if (debug_file) {
-      foreach_sym_core(debug_file, callback, payload, 1);
+      foreach_sym_core(debug_file, callback, option, payload, 1);
       free(debug_file);
     }
   }
 
-  res = listsymbols(e, callback, payload);
+  res = listsymbols(e, callback, payload, option);
   elf_end(e);
   close(fd);
   return res;
 }
 
 int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback,
-                        void *payload) {
-  return foreach_sym_core(path, callback, payload, 0);
+                        void *option, void *payload) {
+  return foreach_sym_core(
+      path, callback, (struct bcc_symbol_option*)option, payload, 0);
 }
 
 static int loadaddr(Elf *e, uint64_t *addr) {
index e87b037f81511a37ea5d592eba6e94119a1090ff..bece58673f527766caf6b9f671539c6cc378f3b1 100644 (file)
@@ -40,7 +40,7 @@ int bcc_elf_foreach_usdt(const char *path, bcc_elf_probecb callback,
                          void *payload);
 int bcc_elf_loadaddr(const char *path, uint64_t *address);
 int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback,
-                        void *payload);
+                        void *option, void *payload);
 
 int bcc_elf_get_type(const char *path);
 int bcc_elf_is_shared_obj(const char *path);
index 46f477ec845735fec32fe684a3f6ae5b3b251a0b..bb5aa05b9e10e3db83b02a5e6e4eb3d2410d5fea 100644 (file)
@@ -31,6 +31,14 @@ struct bcc_symbol {
 
 typedef int (*SYM_CB)(const char *symname, uint64_t addr);
 
+static const uint32_t BCC_SYM_ALL_TYPES = 65535;
+struct bcc_symbol_option {
+  int use_debug_file;
+  int check_debug_file_crc;
+  // Bitmask flags indicating what types of ELF symbols to use
+  uint32_t use_symbol_type;
+};
+
 void *bcc_symcache_new(int pid);
 void bcc_free_symcache(void *symcache, int pid);
 
index ef95074b6f89e57944095db710ffca62ebe07a41..b00277ec09154e22ffc599e2cb84526cd92f182d 100644 (file)
@@ -114,6 +114,12 @@ struct bcc_symbol {
        uint64_t offset;
 };
 
+struct bcc_symbol_option {
+  int use_debug_file;
+  int check_debug_file_crc;
+  uint32_t use_symbol_type;
+};
+
 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);
index 0bba2c6587944bde491e4d9af1635ba835cab7a0..0c87214d9ad0e090975b1f8044f85d9a0ed649a4 100644 (file)
@@ -133,6 +133,13 @@ class bcc_symbol(ct.Structure):
             ('offset', ct.c_ulonglong),
         ]
 
+class bcc_symbol_option(ct.Structure):
+    _fields_ = [
+            ('use_debug_file', ct.c_int),
+            ('check_debug_file_crc', ct.c_int),
+            ('use_symbol_type', ct.c_uint),
+        ]
+
 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