summaryrefslogtreecommitdiffstats
path: root/lib/libproc/proc_sym.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libproc/proc_sym.c')
-rw-r--r--lib/libproc/proc_sym.c77
1 files changed, 51 insertions, 26 deletions
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index 1d56df0..4bef7f0 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -46,9 +46,31 @@
#include "_libproc.h"
+extern char *__cxa_demangle(const char *, char *, size_t *, int *);
+
static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
static void
+demangle(const char *symbol, char *buf, size_t len)
+{
+ char *dembuf;
+ size_t demlen = len;
+
+ dembuf = malloc(len);
+ if (!dembuf)
+ goto fail;
+ dembuf = __cxa_demangle(symbol, dembuf, &demlen, NULL);
+ if (!dembuf)
+ goto fail;
+ strlcpy(buf, dembuf, len);
+ free(dembuf);
+
+ return;
+fail:
+ strlcpy(buf, symbol, len);
+}
+
+static void
proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
{
map->pr_vaddr = rdl->rdl_saddr;
@@ -254,7 +276,7 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
*/
if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
+ goto symtab;
}
i = 0;
while (gelf_getsym(data, i++, &sym) != NULL) {
@@ -266,7 +288,10 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
if (addr >= rsym && addr <= (rsym + sym.st_size)) {
s = elf_strptr(e, dynsymstridx, sym.st_name);
if (s) {
- strlcpy(name, s, namesz);
+ if (s[0] == '_' && s[1] == 'Z' && s[2])
+ demangle(s, name, namesz);
+ else
+ strlcpy(name, s, namesz);
memcpy(symcopy, &sym, sizeof(sym));
/*
* DTrace expects the st_value to contain
@@ -274,11 +299,11 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
* the function.
*/
symcopy->st_value = rsym;
- error = 0;
goto out;
}
}
}
+symtab:
/*
* Iterate over the Symbols Table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
@@ -302,7 +327,10 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
if (addr >= rsym && addr <= (rsym + sym.st_size)) {
s = elf_strptr(e, symtabstridx, sym.st_name);
if (s) {
- strlcpy(name, s, namesz);
+ if (s[0] == '_' && s[1] == 'Z' && s[2])
+ demangle(s, name, namesz);
+ else
+ strlcpy(name, s, namesz);
memcpy(symcopy, &sym, sizeof(sym));
/*
* DTrace expects the st_value to contain
@@ -430,18 +458,17 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
* Iterate over the Dynamic Symbols table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
*/
- if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
+ if ((data = elf_getdata(dynsymscn, NULL))) {
DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, dynsymstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- symcopy->st_value = map->pr_vaddr + sym.st_value;
- error = 0;
- goto out;
+ i = 0;
+ while (gelf_getsym(data, i++, &sym) != NULL) {
+ s = elf_strptr(e, dynsymstridx, sym.st_name);
+ if (s && strcmp(s, symbol) == 0) {
+ memcpy(symcopy, &sym, sizeof(sym));
+ symcopy->st_value = map->pr_vaddr + sym.st_value;
+ error = 0;
+ goto out;
+ }
}
}
/*
@@ -450,17 +477,15 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
*/
if (symtabscn == NULL)
goto err2;
- if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
- DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, symtabstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- error = 0;
- goto out;
+ if ((data = elf_getdata(symtabscn, NULL))) {
+ i = 0;
+ while (gelf_getsym(data, i++, &sym) != NULL) {
+ s = elf_strptr(e, symtabstridx, sym.st_name);
+ if (s && strcmp(s, symbol) == 0) {
+ memcpy(symcopy, &sym, sizeof(sym));
+ error = 0;
+ goto out;
+ }
}
}
out:
OpenPOWER on IntegriCloud