mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-29 13:15:05 +00:00
Factor out some of the duplicated code in the symbol lookup functions, in
preparation for adding userland CTF support to DTrace. MFC after: 1 month Sponsored by: EMC / Isilon Storage Division
This commit is contained in:
parent
43776a00e2
commit
540cc663b1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272125
|
@ -26,20 +26,20 @@
|
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libutil.h>
|
||||
|
@ -228,22 +228,56 @@ proc_addr2map(struct proc_handle *p, uintptr_t addr)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the symbol at addr, returning a copy of the symbol and its name.
|
||||
*/
|
||||
static int
|
||||
lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
|
||||
const char **name, GElf_Sym *symcopy)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
Elf_Data *data;
|
||||
const char *s;
|
||||
uint64_t rsym;
|
||||
int i;
|
||||
|
||||
if ((data = elf_getdata(scn, NULL)) == NULL) {
|
||||
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
|
||||
return (1);
|
||||
}
|
||||
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
|
||||
rsym = off + sym.st_value;
|
||||
if (addr >= rsym && addr < rsym + sym.st_size) {
|
||||
s = elf_strptr(e, stridx, sym.st_name);
|
||||
if (s != NULL) {
|
||||
*name = s;
|
||||
memcpy(symcopy, &sym, sizeof(*symcopy));
|
||||
/*
|
||||
* DTrace expects the st_value to contain
|
||||
* only the address relative to the start of
|
||||
* the function.
|
||||
*/
|
||||
symcopy->st_value = rsym;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
|
||||
size_t namesz, GElf_Sym *symcopy)
|
||||
{
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Shdr shdr;
|
||||
Elf *e;
|
||||
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
|
||||
Elf_Data *data;
|
||||
GElf_Shdr shdr;
|
||||
GElf_Sym sym;
|
||||
GElf_Ehdr ehdr;
|
||||
int fd, error = -1;
|
||||
size_t i;
|
||||
uint64_t rsym;
|
||||
prmap_t *map;
|
||||
char *s;
|
||||
unsigned long symtabstridx = 0, dynsymstridx = 0;
|
||||
const char *s;
|
||||
uintptr_t off;
|
||||
u_long symtabstridx = 0, dynsymstridx = 0;
|
||||
int fd, error = -1;
|
||||
|
||||
if ((map = proc_addr2map(p, addr)) == NULL)
|
||||
return (-1);
|
||||
|
@ -259,6 +293,7 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
|
|||
DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
|
||||
goto err2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the index of the STRTAB and SYMTAB sections to locate
|
||||
* symbol names.
|
||||
|
@ -275,80 +310,25 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
|
|||
dynsymscn = scn;
|
||||
dynsymstridx = shdr.sh_link;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
|
||||
|
||||
/*
|
||||
* Iterate over the Dynamic Symbols table to find the symbol.
|
||||
* Then look up the string name in STRTAB (.dynstr)
|
||||
* First look up the symbol in the dynsymtab, and fall back to the
|
||||
* symtab if the lookup fails.
|
||||
*/
|
||||
if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
|
||||
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
|
||||
goto symtab;
|
||||
}
|
||||
i = 0;
|
||||
while (gelf_getsym(data, i++, &sym) != NULL) {
|
||||
/*
|
||||
* Calculate the address mapped to the virtual memory
|
||||
* by rtld.
|
||||
*/
|
||||
if (ehdr.e_type != ET_EXEC)
|
||||
rsym = map->pr_vaddr + sym.st_value;
|
||||
else
|
||||
rsym = sym.st_value;
|
||||
if (addr >= rsym && addr < rsym + sym.st_size) {
|
||||
s = elf_strptr(e, dynsymstridx, sym.st_name);
|
||||
if (s) {
|
||||
demangle(s, name, namesz);
|
||||
memcpy(symcopy, &sym, sizeof(sym));
|
||||
/*
|
||||
* DTrace expects the st_value to contain
|
||||
* only the address relative to the start of
|
||||
* 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)
|
||||
*/
|
||||
if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
|
||||
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
|
||||
goto err2;
|
||||
}
|
||||
i = 0;
|
||||
while (gelf_getsym(data, i++, &sym) != NULL) {
|
||||
/*
|
||||
* Calculate the address mapped to the virtual memory
|
||||
* by rtld.
|
||||
*/
|
||||
if (ehdr.e_type != ET_EXEC)
|
||||
rsym = map->pr_vaddr + sym.st_value;
|
||||
else
|
||||
rsym = sym.st_value;
|
||||
if (addr >= rsym && addr < rsym + sym.st_size) {
|
||||
s = elf_strptr(e, symtabstridx, sym.st_name);
|
||||
if (s) {
|
||||
demangle(s, name, namesz);
|
||||
memcpy(symcopy, &sym, sizeof(sym));
|
||||
/*
|
||||
* DTrace expects the st_value to contain
|
||||
* only the address relative to the start of
|
||||
* the function.
|
||||
*/
|
||||
symcopy->st_value = rsym;
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
|
||||
if (error == 0)
|
||||
goto out;
|
||||
|
||||
error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
|
||||
if (error == 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
demangle(s, name, namesz);
|
||||
err2:
|
||||
elf_end(e);
|
||||
err1:
|
||||
|
@ -363,7 +343,7 @@ proc_name2map(struct proc_handle *p, const char *name)
|
|||
{
|
||||
size_t i;
|
||||
int cnt;
|
||||
prmap_t *map;
|
||||
prmap_t *map = NULL;
|
||||
char tmppath[MAXPATHLEN];
|
||||
struct kinfo_vmentry *kves, *kve;
|
||||
rd_loadobj_t *rdl;
|
||||
|
@ -382,30 +362,52 @@ proc_name2map(struct proc_handle *p, const char *name)
|
|||
basename_r(kve->kve_path, tmppath);
|
||||
if (strcmp(tmppath, name) == 0) {
|
||||
map = proc_addr2map(p, kve->kve_start);
|
||||
free(kves);
|
||||
return (map);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(kves);
|
||||
return (NULL);
|
||||
}
|
||||
if ((name == NULL || strcmp(name, "a.out") == 0) &&
|
||||
p->rdexec != NULL) {
|
||||
} else
|
||||
for (i = 0; i < p->nobjs; i++) {
|
||||
rdl = &p->rdobjs[i];
|
||||
basename_r(rdl->rdl_path, tmppath);
|
||||
if (strcmp(tmppath, name) == 0) {
|
||||
if ((map = malloc(sizeof(*map))) == NULL)
|
||||
return (NULL);
|
||||
proc_rdl2prmap(rdl, map);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
|
||||
map = proc_addr2map(p, p->rdexec->rdl_saddr);
|
||||
return (map);
|
||||
|
||||
return (map);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the symbol with the given name and return a copy of it.
|
||||
*/
|
||||
static int
|
||||
lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
|
||||
GElf_Sym *symcopy)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
Elf_Data *data;
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if ((data = elf_getdata(scn, NULL)) == NULL) {
|
||||
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
|
||||
return (1);
|
||||
}
|
||||
for (i = 0; i < p->nobjs; i++) {
|
||||
rdl = &p->rdobjs[i];
|
||||
basename_r(rdl->rdl_path, tmppath);
|
||||
if (strcmp(tmppath, name) == 0) {
|
||||
if ((map = malloc(sizeof(*map))) == NULL)
|
||||
return (NULL);
|
||||
proc_rdl2prmap(rdl, map);
|
||||
return (map);
|
||||
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
|
||||
s = elf_strptr(e, stridx, sym.st_name);
|
||||
if (s != NULL && strcmp(s, symbol) == 0) {
|
||||
memcpy(symcopy, &sym, sizeof(*symcopy));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -414,15 +416,12 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
|
|||
{
|
||||
Elf *e;
|
||||
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
|
||||
Elf_Data *data;
|
||||
GElf_Shdr shdr;
|
||||
GElf_Sym sym;
|
||||
GElf_Ehdr ehdr;
|
||||
int fd, error = -1;
|
||||
size_t i;
|
||||
prmap_t *map;
|
||||
char *s;
|
||||
unsigned long symtabstridx = 0, dynsymstridx = 0;
|
||||
uintptr_t off;
|
||||
u_long symtabstridx = 0, dynsymstridx = 0;
|
||||
int fd, error = -1;
|
||||
|
||||
if ((map = proc_name2map(p, object)) == NULL) {
|
||||
DPRINTFX("ERROR: couldn't find object %s", object);
|
||||
|
@ -456,46 +455,25 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
|
|||
dynsymscn = scn;
|
||||
dynsymstridx = shdr.sh_link;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the Dynamic Symbols table to find the symbol.
|
||||
* Then look up the string name in STRTAB (.dynstr)
|
||||
* First look up the symbol in the dynsymtab, and fall back to the
|
||||
* symtab if the lookup fails.
|
||||
*/
|
||||
if ((data = elf_getdata(dynsymscn, NULL))) {
|
||||
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));
|
||||
if (ehdr.e_type != ET_EXEC)
|
||||
symcopy->st_value += map->pr_vaddr;
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Iterate over the Symbols Table to find the symbol.
|
||||
* Then look up the string name in STRTAB (.dynstr)
|
||||
*/
|
||||
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));
|
||||
if (ehdr.e_type != ET_EXEC)
|
||||
symcopy->st_value += map->pr_vaddr;
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy);
|
||||
if (error == 0)
|
||||
goto out;
|
||||
|
||||
error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy);
|
||||
if (error == 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
DPRINTFX("found addr 0x%lx for %s", symcopy->st_value, symbol);
|
||||
off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
|
||||
symcopy->st_value += off;
|
||||
|
||||
err2:
|
||||
elf_end(e);
|
||||
err1:
|
||||
|
@ -506,7 +484,6 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
|
|||
return (error);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
|
||||
int mask, proc_sym_f *func, void *cd)
|
||||
|
@ -543,7 +520,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
|
|||
scn = NULL;
|
||||
while ((scn = elf_nextscn(e, scn)) != NULL) {
|
||||
gelf_getshdr(scn, &shdr);
|
||||
if (which == PR_SYMTAB &&
|
||||
if (which == PR_SYMTAB &&
|
||||
shdr.sh_type == SHT_SYMTAB) {
|
||||
foundscn = scn;
|
||||
break;
|
||||
|
@ -560,8 +537,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
|
|||
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
|
||||
goto err2;
|
||||
}
|
||||
i = 0;
|
||||
while (gelf_getsym(data, i++, &sym) != NULL) {
|
||||
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
|
||||
if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
|
||||
(mask & BIND_LOCAL) == 0)
|
||||
continue;
|
||||
|
|
Loading…
Reference in a new issue