}
}
-bool KSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym) {
+bool KSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle) {
refresh();
if (syms_.empty()) {
auto it = std::upper_bound(syms_.begin(), syms_.end(), Symbol("", addr)) - 1;
sym->name = (*it).name.c_str();
- sym->demangle_name = sym->name;
+ if (demangle)
+ sym->demangle_name = sym->name;
sym->module = "kernel";
sym->offset = addr - (*it).addr;
return true;
return 0;
}
-bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym) {
+bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym,
+ bool demangle) {
if (procstat_.is_stale())
refresh();
for (Module &mod : modules_) {
if (mod.contains(addr)) {
bool res = mod.find_addr(addr, sym);
- if (sym->name) {
- sym->demangle_name = abi::__cxa_demangle(sym->name, nullptr, nullptr, nullptr);
+ if (demangle) {
+ if (sym->name)
+ sym->demangle_name =
+ abi::__cxa_demangle(sym->name, nullptr, nullptr, nullptr);
if (!sym->demangle_name)
sym->demangle_name = sym->name;
}
return cache->resolve_addr(addr, sym) ? 0 : -1;
}
+int bcc_symcache_resolve_no_demangle(void *resolver, uint64_t addr,
+ struct bcc_symbol *sym) {
+ SymbolCache *cache = static_cast<SymbolCache *>(resolver);
+ return cache->resolve_addr(addr, sym, false) ? 0 : -1;
+}
+
int bcc_symcache_resolve_name(void *resolver, const char *module,
const char *name, uint64_t *addr) {
SymbolCache *cache = static_cast<SymbolCache *>(resolver);
uint64_t offset;
};
-typedef int(* SYM_CB)(const char *symname, uint64_t addr);
+typedef int (*SYM_CB)(const char *symname, uint64_t addr);
void *bcc_symcache_new(int pid);
void bcc_free_symcache(void *symcache, int pid);
int bcc_symcache_resolve(void *symcache, uint64_t addr, struct bcc_symbol *sym);
+int bcc_symcache_resolve_no_demangle(void *symcache, uint64_t addr,
+ struct bcc_symbol *sym);
+
int bcc_symcache_resolve_name(void *resolver, const char *module,
const char *name, uint64_t *addr);
void bcc_symcache_refresh(void *resolver);
virtual ~SymbolCache() = default;
virtual void refresh() = 0;
- virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym) = 0;
+ virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) = 0;
virtual bool resolve_name(const char *module, const char *name,
uint64_t *addr) = 0;
};
static void _add_symbol(const char *, uint64_t, void *);
public:
- virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym);
+ virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true);
virtual bool resolve_name(const char *unused, const char *name,
uint64_t *addr);
virtual void refresh();
public:
ProcSyms(int pid);
virtual void refresh();
- virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym);
+ virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true);
virtual bool resolve_name(const char *module, const char *name,
uint64_t *addr);
};
def __init__(self, pid):
self.cache = lib.bcc_symcache_new(pid)
- def resolve(self, addr):
+ def resolve(self, addr, demangle):
"""
Return a tuple of the symbol (function), its offset from the beginning
of the function, and the module in which it lies. For example:
"""
sym = bcc_symbol()
psym = ct.pointer(sym)
- if lib.bcc_symcache_resolve(self.cache, addr, psym) < 0:
+ if demangle:
+ res = lib.bcc_symcache_resolve(self.cache, addr, psym)
+ else:
+ res = lib.bcc_symcache_resolve_no_demangle(self.cache, addr, psym)
+ if res < 0:
if sym.module and sym.offset:
return (None, sym.offset,
ct.cast(sym.module, ct.c_char_p).value.decode())
return (None, addr, None)
- return (sym.demangle_name.decode(), sym.offset,
- ct.cast(sym.module, ct.c_char_p).value.decode())
+ return (
+ sym.demangle_name.decode() if demangle else sym.name.decode(),
+ sym.offset, ct.cast(sym.module, ct.c_char_p).value.decode())
def resolve_name(self, module, name):
addr = ct.c_ulonglong()
return BPF._sym_caches[pid]
@staticmethod
- def sym(addr, pid, show_module=False, show_offset=False):
+ def sym(addr, pid, show_module=False, show_offset=False, demangle=True):
"""sym(addr, pid, show_module=False, show_offset=False)
Translate a memory address into a function name for a pid, which is
Example output when both show_module and show_offset are False:
"start_thread"
"""
- name, offset, module = BPF._sym_cache(pid).resolve(addr)
+ name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle)
offset = "+0x%x" % offset if show_offset and name is not None else ""
name = name or "[unknown]"
name = name + offset
Example output when both show_module and show_offset are True:
"default_idle+0x0 [kernel]"
"""
- return BPF.sym(addr, -1, show_module, show_offset)
+ return BPF.sym(addr, -1, show_module, show_offset, False)
@staticmethod
def ksymname(name):
lib.bcc_symcache_resolve.restype = ct.c_int
lib.bcc_symcache_resolve.argtypes = [ct.c_void_p, ct.c_ulonglong, ct.POINTER(bcc_symbol)]
+lib.bcc_symcache_resolve_no_demangle.restype = ct.c_int
+lib.bcc_symcache_resolve_no_demangle.argtypes = [ct.c_void_p, ct.c_ulonglong, ct.POINTER(bcc_symbol)]
+
lib.bcc_symcache_resolve_name.restype = ct.c_int
lib.bcc_symcache_resolve_name.argtypes = [
ct.c_void_p, ct.c_char_p, ct.c_char_p, ct.POINTER(ct.c_ulonglong)]
+++ /dev/null
-#include <unistd.h>
-#include <stdio.h>
-
-static __attribute__((noinline)) int some_function(int x, int y) {
- volatile int z = x + y;
- return z;
-}
-
-int main() {
- printf("%p\n", &some_function);
- fflush(stdout);
- printf("result = %d\n", some_function(42, 11));
- sleep(1000);
- return 0;
-}
--- /dev/null
+#include <unistd.h>
+#include <cstdio>
+
+namespace some_namespace {
+ static __attribute__((noinline)) int some_function(int x, int y) {
+ volatile int z = x + y;
+ return z;
+ }
+}
+
+int main() {
+ printf("%p\n", &some_namespace::some_function);
+ fflush(stdout);
+ printf("result = %d\n", some_namespace::some_function(42, 11));
+ sleep(1000);
+ return 0;
+}
self.process.wait()
def resolve_addr(self):
- sym, offset, module = self.syms.resolve(self.addr)
- self.assertEqual(sym, 'some_function')
+ sym, offset, module = self.syms.resolve(self.addr, False)
+ self.assertEqual(sym, self.mangled_name)
+ self.assertEqual(offset, 0)
+ self.assertTrue(module[-5:] == 'dummy')
+ sym, offset, module = self.syms.resolve(self.addr, True)
+ self.assertEqual(sym, 'some_namespace::some_function(int, int)')
self.assertEqual(offset, 0)
self.assertTrue(module[-5:] == 'dummy')
+
def resolve_name(self):
script_dir = os.path.dirname(os.path.realpath(__file__))
addr = self.syms.resolve_name(os.path.join(script_dir, 'dummy'),
- 'some_function')
+ self.mangled_name)
self.assertEqual(addr, self.addr)
pass
class TestDebuglink(Harness):
def build_command(self):
- subprocess.check_output('gcc -o dummy dummy.c'.split())
+ subprocess.check_output('g++ -o dummy dummy.cc'.split())
+ lines = subprocess.check_output('nm dummy'.split()).splitlines()
+ for line in lines:
+ if "some_function" in line:
+ self.mangled_name = line.split(' ')[2]
+ break
+ self.assertTrue(self.mangled_name)
def debug_command(self):
subprocess.check_output('objcopy --add-gnu-debuglink=dummy.debug dummy'
class TestBuildid(Harness):
def build_command(self):
- subprocess.check_output(('gcc -o dummy -Xlinker ' + \
- '--build-id=0x123456789abcdef0123456789abcdef012345678 dummy.c')
+ subprocess.check_output(('g++ -o dummy -Xlinker ' + \
+ '--build-id=0x123456789abcdef0123456789abcdef012345678 dummy.cc')
.split())
+ lines = subprocess.check_output('nm dummy'.split()).splitlines()
+ for line in lines:
+ if "some_function" in line:
+ self.mangled_name = line.split(' ')[2]
+ break
+ self.assertTrue(self.mangled_name)
+
def debug_command(self):
subprocess.check_output('mkdir -p /usr/lib/debug/.build-id/12'.split())