2 * Copyright (c) 2010 The FreeBSD Foundation
3 * Copyright (c) 2008 John Birrell (jb@freebsd.org)
6 * Portions of this software were developed by Rui Paulo under sponsorship
7 * from the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/types.h>
49 #ifndef NO_CXA_DEMANGLE
50 extern char *__cxa_demangle(const char *, char *, size_t *, int *);
51 #endif /* NO_CXA_DEMANGLE */
53 static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
56 demangle(const char *symbol, char *buf, size_t len)
58 #ifndef NO_CXA_DEMANGLE
61 if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) {
62 dembuf = __cxa_demangle(symbol, NULL, NULL, NULL);
65 strlcpy(buf, dembuf, len);
70 #endif /* NO_CXA_DEMANGLE */
71 strlcpy(buf, symbol, len);
75 find_dbg_obj(const char *path)
78 char dbg_path[PATH_MAX];
80 snprintf(dbg_path, sizeof(dbg_path),
81 "/usr/lib/debug/%s.debug", path);
82 fd = open(dbg_path, O_RDONLY);
86 return (open(path, O_RDONLY));
90 proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
92 map->pr_vaddr = rdl->rdl_saddr;
93 map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
94 map->pr_offset = rdl->rdl_offset;
96 if (rdl->rdl_prot & RD_RDL_R)
97 map->pr_mflags |= MA_READ;
98 if (rdl->rdl_prot & RD_RDL_W)
99 map->pr_mflags |= MA_WRITE;
100 if (rdl->rdl_prot & RD_RDL_X)
101 map->pr_mflags |= MA_EXEC;
102 strlcpy(map->pr_mapname, rdl->rdl_path,
103 sizeof(map->pr_mapname));
107 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
113 for (i = 0; i < p->nobjs; i++) {
115 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
116 strlcpy(objname, rdl->rdl_path, objnamesz);
124 proc_obj2map(struct proc_handle *p, const char *objname)
129 char path[MAXPATHLEN];
132 for (i = 0; i < p->nobjs; i++) {
133 basename_r(p->rdobjs[i].rdl_path, path);
134 if (strcmp(path, objname) == 0) {
140 if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
146 if ((map = malloc(sizeof(*map))) == NULL)
148 proc_rdl2prmap(rdl, map);
153 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd)
158 char path[MAXPATHLEN];
159 char last[MAXPATHLEN];
163 memset(last, 0, sizeof(last));
164 for (i = 0; i < p->nobjs; i++) {
166 proc_rdl2prmap(rdl, &map);
167 basename_r(rdl->rdl_path, path);
169 * We shouldn't call the callback twice with the same object.
170 * To do that we are assuming the fact that if there are
171 * repeated object names (i.e. different mappings for the
172 * same object) they occur next to each other.
174 if (strcmp(path, last) == 0)
176 (*func)(cd, &map, path);
177 strlcpy(last, path, sizeof(last));
184 proc_addr2map(struct proc_handle *p, uintptr_t addr)
190 struct kinfo_vmentry *kves, *kve;
193 * If we don't have a cache of listed objects, we need to query
197 if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL)
199 for (i = 0; i < (size_t)cnt; i++) {
201 if (kve->kve_type == KVME_TYPE_VNODE)
203 if (addr >= kve->kve_start && addr < kve->kve_end) {
204 if ((map = malloc(sizeof(*map))) == NULL) {
208 map->pr_vaddr = kve->kve_start;
209 map->pr_size = kve->kve_end - kve->kve_start;
210 map->pr_offset = kve->kve_offset;
212 if (kve->kve_protection & KVME_PROT_READ)
213 map->pr_mflags |= MA_READ;
214 if (kve->kve_protection & KVME_PROT_WRITE)
215 map->pr_mflags |= MA_WRITE;
216 if (kve->kve_protection & KVME_PROT_EXEC)
217 map->pr_mflags |= MA_EXEC;
218 if (kve->kve_flags & KVME_FLAG_COW)
219 map->pr_mflags |= MA_COW;
220 if (kve->kve_flags & KVME_FLAG_NEEDS_COPY)
221 map->pr_mflags |= MA_NEEDS_COPY;
222 if (kve->kve_flags & KVME_FLAG_NOCOREDUMP)
223 map->pr_mflags |= MA_NOCOREDUMP;
224 strlcpy(map->pr_mapname, kves[lastvn].kve_path,
225 sizeof(map->pr_mapname));
234 for (i = 0; i < p->nobjs; i++) {
236 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
237 if ((map = malloc(sizeof(*map))) == NULL)
239 proc_rdl2prmap(rdl, map);
247 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
248 size_t namesz, GElf_Sym *symcopy)
251 Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
261 unsigned long symtabstridx = 0, dynsymstridx = 0;
263 if ((map = proc_addr2map(p, addr)) == NULL)
265 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
266 DPRINTF("ERROR: open %s failed", map->pr_mapname);
269 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
270 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
273 if (gelf_getehdr(e, &ehdr) == NULL) {
274 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
278 * Find the index of the STRTAB and SYMTAB sections to locate
282 while ((scn = elf_nextscn(e, scn)) != NULL) {
283 gelf_getshdr(scn, &shdr);
284 switch (shdr.sh_type) {
287 symtabstridx = shdr.sh_link;
291 dynsymstridx = shdr.sh_link;
298 * Iterate over the Dynamic Symbols table to find the symbol.
299 * Then look up the string name in STRTAB (.dynstr)
301 if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
302 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
306 while (gelf_getsym(data, i++, &sym) != NULL) {
308 * Calculate the address mapped to the virtual memory
311 if (ehdr.e_type != ET_EXEC)
312 rsym = map->pr_vaddr + sym.st_value;
315 if (addr >= rsym && addr < rsym + sym.st_size) {
316 s = elf_strptr(e, dynsymstridx, sym.st_name);
318 demangle(s, name, namesz);
319 memcpy(symcopy, &sym, sizeof(sym));
321 * DTrace expects the st_value to contain
322 * only the address relative to the start of
325 symcopy->st_value = rsym;
333 * Iterate over the Symbols Table to find the symbol.
334 * Then look up the string name in STRTAB (.dynstr)
336 if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
337 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
341 while (gelf_getsym(data, i++, &sym) != NULL) {
343 * Calculate the address mapped to the virtual memory
346 if (ehdr.e_type != ET_EXEC)
347 rsym = map->pr_vaddr + sym.st_value;
350 if (addr >= rsym && addr < rsym + sym.st_size) {
351 s = elf_strptr(e, symtabstridx, sym.st_name);
353 demangle(s, name, namesz);
354 memcpy(symcopy, &sym, sizeof(sym));
356 * DTrace expects the st_value to contain
357 * only the address relative to the start of
360 symcopy->st_value = rsym;
377 proc_name2map(struct proc_handle *p, const char *name)
382 char tmppath[MAXPATHLEN];
383 struct kinfo_vmentry *kves, *kve;
387 * If we haven't iterated over the list of loaded objects,
388 * librtld_db isn't yet initialized and it's very likely
389 * that librtld_db called us. We need to do the heavy
390 * lifting here to find the symbol librtld_db is looking for.
393 if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
395 for (i = 0; i < (size_t)cnt; i++) {
397 basename_r(kve->kve_path, tmppath);
398 if (strcmp(tmppath, name) == 0) {
399 map = proc_addr2map(p, kve->kve_start);
407 if ((name == NULL || strcmp(name, "a.out") == 0) &&
409 map = proc_addr2map(p, p->rdexec->rdl_saddr);
412 for (i = 0; i < p->nobjs; i++) {
414 basename_r(rdl->rdl_path, tmppath);
415 if (strcmp(tmppath, name) == 0) {
416 if ((map = malloc(sizeof(*map))) == NULL)
418 proc_rdl2prmap(rdl, map);
427 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
431 Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
440 unsigned long symtabstridx = 0, dynsymstridx = 0;
442 if ((map = proc_name2map(p, object)) == NULL) {
443 DPRINTFX("ERROR: couldn't find object %s", object);
446 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
447 DPRINTF("ERROR: open %s failed", map->pr_mapname);
450 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
451 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
454 if (gelf_getehdr(e, &ehdr) == NULL) {
455 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
459 * Find the index of the STRTAB and SYMTAB sections to locate
463 while ((scn = elf_nextscn(e, scn)) != NULL) {
464 gelf_getshdr(scn, &shdr);
465 switch (shdr.sh_type) {
468 symtabstridx = shdr.sh_link;
472 dynsymstridx = shdr.sh_link;
479 * Iterate over the Dynamic Symbols table to find the symbol.
480 * Then look up the string name in STRTAB (.dynstr)
482 if ((data = elf_getdata(dynsymscn, NULL))) {
484 while (gelf_getsym(data, i++, &sym) != NULL) {
485 s = elf_strptr(e, dynsymstridx, sym.st_name);
486 if (s && strcmp(s, symbol) == 0) {
487 memcpy(symcopy, &sym, sizeof(sym));
488 if (ehdr.e_type != ET_EXEC)
489 symcopy->st_value += map->pr_vaddr;
496 * Iterate over the Symbols Table to find the symbol.
497 * Then look up the string name in STRTAB (.dynstr)
499 if ((data = elf_getdata(symtabscn, NULL))) {
501 while (gelf_getsym(data, i++, &sym) != NULL) {
502 s = elf_strptr(e, symtabstridx, sym.st_name);
503 if (s && strcmp(s, symbol) == 0) {
504 memcpy(symcopy, &sym, sizeof(sym));
505 if (ehdr.e_type != ET_EXEC)
506 symcopy->st_value += map->pr_vaddr;
513 DPRINTFX("found addr 0x%lx for %s", symcopy->st_value, symbol);
526 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
527 int mask, proc_sym_f *func, void *cd)
532 Elf_Scn *scn, *foundscn = NULL;
537 unsigned long stridx = -1;
541 if ((map = proc_name2map(p, object)) == NULL)
543 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
544 DPRINTF("ERROR: open %s failed", map->pr_mapname);
547 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
548 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
551 if (gelf_getehdr(e, &ehdr) == NULL) {
552 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
556 * Find the section we are looking for.
559 while ((scn = elf_nextscn(e, scn)) != NULL) {
560 gelf_getshdr(scn, &shdr);
561 if (which == PR_SYMTAB &&
562 shdr.sh_type == SHT_SYMTAB) {
565 } else if (which == PR_DYNSYM &&
566 shdr.sh_type == SHT_DYNSYM) {
573 stridx = shdr.sh_link;
574 if ((data = elf_getdata(foundscn, NULL)) == NULL) {
575 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
579 while (gelf_getsym(data, i++, &sym) != NULL) {
580 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
581 (mask & BIND_LOCAL) == 0)
583 if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL &&
584 (mask & BIND_GLOBAL) == 0)
586 if (GELF_ST_BIND(sym.st_info) == STB_WEAK &&
587 (mask & BIND_WEAK) == 0)
589 if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE &&
590 (mask & TYPE_NOTYPE) == 0)
592 if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT &&
593 (mask & TYPE_OBJECT) == 0)
595 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC &&
596 (mask & TYPE_FUNC) == 0)
598 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
599 (mask & TYPE_SECTION) == 0)
601 if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
602 (mask & TYPE_FILE) == 0)
604 s = elf_strptr(e, stridx, sym.st_name);
605 if (ehdr.e_type != ET_EXEC)
606 sym.st_value += map->pr_vaddr;
607 (*func)(cd, &sym, s);