1 /*- 2 * Copyright (c) 2010 The FreeBSD Foundation 3 * Copyright (c) 2008 John Birrell (jb@freebsd.org) 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Rui Paulo under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 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. 17 * 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 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #ifdef __FBSDID 33 __FBSDID("$FreeBSD: head/lib/libproc/proc_sym.c 279946 2015-03-13 04:26:48Z stas $"); 34 #else 35 __RCSID("$NetBSD: proc_sym.c,v 1.3 2016/04/26 14:28:39 chs Exp $"); 36 #endif 37 38 #include <sys/types.h> 39 #ifndef NO_CTF 40 #include <sys/ctf.h> 41 #include <sys/ctf_api.h> 42 #endif 43 #include <sys/user.h> 44 #include <sys/sysctl.h> 45 46 #include <assert.h> 47 #include <err.h> 48 #include <fcntl.h> 49 #include <libgen.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #ifndef NO_CTF 55 #include <libctf.h> 56 #endif 57 #include <util.h> 58 59 #include "_libproc.h" 60 61 #define DBG_PATH_FMT "/usr/libdata/debug/%s.debug" 62 63 #ifdef NO_CTF 64 typedef struct ctf_file ctf_file_t; 65 #endif 66 67 #ifndef NO_CXA_DEMANGLE 68 extern char *__cxa_demangle(const char *, char *, size_t *, int *); 69 #endif /* NO_CXA_DEMANGLE */ 70 71 static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *); 72 73 #ifdef __NetBSD__ 74 static char *basename_r(const char *path, char *buf) 75 { 76 // We "know" this works. 77 if (path[0]) 78 strlcpy(buf, strrchr(path, '/') + 1, PATH_MAX); 79 else 80 buf[0] = '\0'; 81 return buf; 82 } 83 #endif 84 85 static void 86 demangle(const char *symbol, char *buf, size_t len) 87 { 88 #ifndef NO_CXA_DEMANGLE 89 char *dembuf; 90 91 if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) { 92 dembuf = __cxa_demangle(symbol, NULL, NULL, NULL); 93 if (!dembuf) 94 goto fail; 95 strlcpy(buf, dembuf, len); 96 free(dembuf); 97 return; 98 } 99 fail: 100 #endif /* NO_CXA_DEMANGLE */ 101 strlcpy(buf, symbol, len); 102 } 103 104 static int 105 find_dbg_obj(const char *path) 106 { 107 int fd; 108 char dbg_path[PATH_MAX]; 109 110 snprintf(dbg_path, sizeof(dbg_path), DBG_PATH_FMT, path); 111 fd = open(dbg_path, O_RDONLY); 112 if (fd >= 0) 113 return (fd); 114 else 115 return (open(path, O_RDONLY)); 116 } 117 118 static void 119 proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map) 120 { 121 map->pr_vaddr = rdl->rdl_saddr; 122 map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr; 123 map->pr_offset = rdl->rdl_offset; 124 map->pr_mflags = 0; 125 if (rdl->rdl_prot & RD_RDL_R) 126 map->pr_mflags |= MA_READ; 127 if (rdl->rdl_prot & RD_RDL_W) 128 map->pr_mflags |= MA_WRITE; 129 if (rdl->rdl_prot & RD_RDL_X) 130 map->pr_mflags |= MA_EXEC; 131 strlcpy(map->pr_mapname, rdl->rdl_path, 132 sizeof(map->pr_mapname)); 133 } 134 135 char * 136 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname, 137 size_t objnamesz) 138 { 139 size_t i; 140 rd_loadobj_t *rdl; 141 142 for (i = 0; i < p->nobjs; i++) { 143 rdl = &p->rdobjs[i]; 144 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { 145 strlcpy(objname, rdl->rdl_path, objnamesz); 146 return (objname); 147 } 148 } 149 return (NULL); 150 } 151 152 prmap_t * 153 proc_obj2map(struct proc_handle *p, const char *objname) 154 { 155 size_t i; 156 prmap_t *map; 157 rd_loadobj_t *rdl; 158 char path[MAXPATHLEN]; 159 160 rdl = NULL; 161 for (i = 0; i < p->nobjs; i++) { 162 basename_r(p->rdobjs[i].rdl_path, path); 163 if (strcmp(path, objname) == 0) { 164 rdl = &p->rdobjs[i]; 165 break; 166 } 167 } 168 if (rdl == NULL) { 169 if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL) 170 rdl = p->rdexec; 171 else 172 return (NULL); 173 } 174 175 if ((map = malloc(sizeof(*map))) == NULL) 176 return (NULL); 177 proc_rdl2prmap(rdl, map); 178 return (map); 179 } 180 181 int 182 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd) 183 { 184 size_t i; 185 rd_loadobj_t *rdl; 186 prmap_t map; 187 char path[MAXPATHLEN]; 188 char last[MAXPATHLEN]; 189 int error; 190 191 if (p->nobjs == 0) 192 return (-1); 193 194 error = 0; 195 memset(last, 0, sizeof(last)); 196 for (i = 0; i < p->nobjs; i++) { 197 rdl = &p->rdobjs[i]; 198 proc_rdl2prmap(rdl, &map); 199 basename_r(rdl->rdl_path, path); 200 /* 201 * We shouldn't call the callback twice with the same object. 202 * To do that we are assuming the fact that if there are 203 * repeated object names (i.e. different mappings for the 204 * same object) they occur next to each other. 205 */ 206 if (strcmp(path, last) == 0) 207 continue; 208 if ((error = (*func)(cd, &map, path)) != 0) 209 break; 210 strlcpy(last, path, sizeof(last)); 211 } 212 return (error); 213 } 214 215 prmap_t * 216 proc_addr2map(struct proc_handle *p, uintptr_t addr) 217 { 218 size_t i, cnt, lastvn = 0; 219 prmap_t *map; 220 rd_loadobj_t *rdl; 221 struct kinfo_vmentry *kves, *kve; 222 223 /* 224 * If we don't have a cache of listed objects, we need to query 225 * it ourselves. 226 */ 227 if (p->nobjs == 0) { 228 if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL) 229 return (NULL); 230 for (i = 0; i < (size_t)cnt; i++) { 231 kve = kves + i; 232 if (kve->kve_type == KVME_TYPE_VNODE) 233 lastvn = i; 234 if (addr >= kve->kve_start && addr < kve->kve_end) { 235 if ((map = malloc(sizeof(*map))) == NULL) { 236 free(kves); 237 return (NULL); 238 } 239 map->pr_vaddr = kve->kve_start; 240 map->pr_size = kve->kve_end - kve->kve_start; 241 map->pr_offset = kve->kve_offset; 242 map->pr_mflags = 0; 243 if (kve->kve_protection & KVME_PROT_READ) 244 map->pr_mflags |= MA_READ; 245 if (kve->kve_protection & KVME_PROT_WRITE) 246 map->pr_mflags |= MA_WRITE; 247 if (kve->kve_protection & KVME_PROT_EXEC) 248 map->pr_mflags |= MA_EXEC; 249 if (kve->kve_flags & KVME_FLAG_COW) 250 map->pr_mflags |= MA_COW; 251 if (kve->kve_flags & KVME_FLAG_NEEDS_COPY) 252 map->pr_mflags |= MA_NEEDS_COPY; 253 if (kve->kve_flags & KVME_FLAG_NOCOREDUMP) 254 map->pr_mflags |= MA_NOCOREDUMP; 255 strlcpy(map->pr_mapname, kves[lastvn].kve_path, 256 sizeof(map->pr_mapname)); 257 free(kves); 258 return (map); 259 } 260 } 261 free(kves); 262 return (NULL); 263 } 264 265 for (i = 0; i < p->nobjs; i++) { 266 rdl = &p->rdobjs[i]; 267 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { 268 if ((map = malloc(sizeof(*map))) == NULL) 269 return (NULL); 270 proc_rdl2prmap(rdl, map); 271 return (map); 272 } 273 } 274 return (NULL); 275 } 276 277 /* 278 * Look up the symbol at addr, returning a copy of the symbol and its name. 279 */ 280 static int 281 lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr, 282 const char **name, GElf_Sym *symcopy) 283 { 284 GElf_Sym sym; 285 Elf_Data *data; 286 const char *s; 287 uint64_t rsym; 288 int i; 289 290 if ((data = elf_getdata(scn, NULL)) == NULL) { 291 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 292 return (1); 293 } 294 for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) { 295 rsym = off + sym.st_value; 296 if (addr >= rsym && addr < rsym + sym.st_size) { 297 s = elf_strptr(e, stridx, sym.st_name); 298 if (s != NULL) { 299 *name = s; 300 memcpy(symcopy, &sym, sizeof(*symcopy)); 301 /* 302 * DTrace expects the st_value to contain 303 * only the address relative to the start of 304 * the function. 305 */ 306 symcopy->st_value = rsym; 307 return (0); 308 } 309 } 310 } 311 return (1); 312 } 313 314 int 315 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name, 316 size_t namesz, GElf_Sym *symcopy) 317 { 318 GElf_Ehdr ehdr; 319 GElf_Shdr shdr; 320 Elf *e; 321 Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; 322 prmap_t *map; 323 const char *s; 324 uintptr_t off; 325 u_long symtabstridx = 0, dynsymstridx = 0; 326 int fd, error = -1; 327 328 if ((map = proc_addr2map(p, addr)) == NULL) 329 return (-1); 330 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) { 331 DPRINTF("ERROR: open %s failed", map->pr_mapname); 332 goto err0; 333 } 334 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 335 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 336 goto err1; 337 } 338 if (gelf_getehdr(e, &ehdr) == NULL) { 339 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 340 goto err2; 341 } 342 343 /* 344 * Find the index of the STRTAB and SYMTAB sections to locate 345 * symbol names. 346 */ 347 scn = NULL; 348 while ((scn = elf_nextscn(e, scn)) != NULL) { 349 gelf_getshdr(scn, &shdr); 350 switch (shdr.sh_type) { 351 case SHT_SYMTAB: 352 symtabscn = scn; 353 symtabstridx = shdr.sh_link; 354 break; 355 case SHT_DYNSYM: 356 dynsymscn = scn; 357 dynsymstridx = shdr.sh_link; 358 break; 359 } 360 } 361 362 off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr; 363 364 /* 365 * First look up the symbol in the dynsymtab, and fall back to the 366 * symtab if the lookup fails. 367 */ 368 if (dynsymscn) { 369 error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy); 370 if (error == 0) 371 goto out; 372 } 373 374 error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy); 375 if (error != 0) 376 goto err2; 377 378 out: 379 demangle(s, name, namesz); 380 err2: 381 elf_end(e); 382 err1: 383 close(fd); 384 err0: 385 free(map); 386 return (error); 387 } 388 389 prmap_t * 390 proc_name2map(struct proc_handle *p, const char *name) 391 { 392 size_t i, cnt; 393 prmap_t *map = NULL; 394 char tmppath[MAXPATHLEN]; 395 struct kinfo_vmentry *kves, *kve; 396 rd_loadobj_t *rdl; 397 398 /* 399 * If we haven't iterated over the list of loaded objects, 400 * librtld_db isn't yet initialized and it's very likely 401 * that librtld_db called us. We need to do the heavy 402 * lifting here to find the symbol librtld_db is looking for. 403 */ 404 if (p->nobjs == 0) { 405 if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) 406 return (NULL); 407 for (i = 0; i < (size_t)cnt; i++) { 408 kve = kves + i; 409 basename_r(kve->kve_path, tmppath); 410 if (strcmp(tmppath, name) == 0) { 411 map = proc_addr2map(p, kve->kve_start); 412 break; 413 } 414 } 415 free(kves); 416 } else 417 for (i = 0; i < p->nobjs; i++) { 418 rdl = &p->rdobjs[i]; 419 basename_r(rdl->rdl_path, tmppath); 420 if (strcmp(tmppath, name) == 0) { 421 if ((map = malloc(sizeof(*map))) == NULL) 422 return (NULL); 423 proc_rdl2prmap(rdl, map); 424 break; 425 } 426 } 427 428 if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL) 429 map = proc_addr2map(p, p->rdexec->rdl_saddr); 430 431 return (map); 432 } 433 434 /* 435 * Look up the symbol with the given name and return a copy of it. 436 */ 437 static int 438 lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol, 439 GElf_Sym *symcopy, prsyminfo_t *si) 440 { 441 GElf_Sym sym; 442 Elf_Data *data; 443 char *s; 444 int i; 445 446 if ((data = elf_getdata(scn, NULL)) == NULL) { 447 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 448 return (1); 449 } 450 for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) { 451 s = elf_strptr(e, stridx, sym.st_name); 452 if (s != NULL && strcmp(s, symbol) == 0) { 453 memcpy(symcopy, &sym, sizeof(*symcopy)); 454 if (si != NULL) 455 si->prs_id = i; 456 return (0); 457 } 458 } 459 return (1); 460 } 461 462 int 463 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol, 464 GElf_Sym *symcopy, prsyminfo_t *si) 465 { 466 Elf *e; 467 Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; 468 GElf_Shdr shdr; 469 GElf_Ehdr ehdr; 470 prmap_t *map; 471 uintptr_t off; 472 u_long symtabstridx = 0, dynsymstridx = 0; 473 int fd, error = -1; 474 475 if ((map = proc_name2map(p, object)) == NULL) { 476 DPRINTFX("ERROR: couldn't find object %s", object); 477 goto err0; 478 } 479 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) { 480 DPRINTF("ERROR: open %s failed", map->pr_mapname); 481 goto err0; 482 } 483 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 484 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 485 goto err1; 486 } 487 if (gelf_getehdr(e, &ehdr) == NULL) { 488 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 489 goto err2; 490 } 491 /* 492 * Find the index of the STRTAB and SYMTAB sections to locate 493 * symbol names. 494 */ 495 scn = NULL; 496 while ((scn = elf_nextscn(e, scn)) != NULL) { 497 gelf_getshdr(scn, &shdr); 498 switch (shdr.sh_type) { 499 case SHT_SYMTAB: 500 symtabscn = scn; 501 symtabstridx = shdr.sh_link; 502 break; 503 case SHT_DYNSYM: 504 dynsymscn = scn; 505 dynsymstridx = shdr.sh_link; 506 break; 507 } 508 } 509 510 /* 511 * First look up the symbol in the dynsymtab, and fall back to the 512 * symtab if the lookup fails. 513 */ 514 if (dynsymscn) { 515 error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si); 516 if (error == 0) 517 goto out; 518 } 519 520 error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si); 521 if (error == 0) 522 goto out; 523 524 out: 525 off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr; 526 symcopy->st_value += off; 527 528 err2: 529 elf_end(e); 530 err1: 531 close(fd); 532 err0: 533 free(map); 534 535 return (error); 536 } 537 538 ctf_file_t * 539 proc_name2ctf(struct proc_handle *p, const char *name) 540 { 541 #ifndef NO_CTF 542 ctf_file_t *ctf; 543 prmap_t *map; 544 int error; 545 546 if ((map = proc_name2map(p, name)) == NULL) 547 return (NULL); 548 549 ctf = ctf_open(map->pr_mapname, &error); 550 free(map); 551 return (ctf); 552 #else 553 (void)p; 554 (void)name; 555 return (NULL); 556 #endif 557 } 558 559 int 560 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which, 561 int mask, proc_sym_f *func, void *cd) 562 { 563 Elf *e; 564 int i, fd; 565 prmap_t *map; 566 Elf_Scn *scn, *foundscn = NULL; 567 Elf_Data *data; 568 GElf_Ehdr ehdr; 569 GElf_Shdr shdr; 570 GElf_Sym sym; 571 unsigned long stridx = -1; 572 char *s; 573 int error = -1; 574 575 if ((map = proc_name2map(p, object)) == NULL) 576 return (-1); 577 if ((fd = find_dbg_obj(map->pr_mapname)) < 0) { 578 DPRINTF("ERROR: open %s failed", map->pr_mapname); 579 goto err0; 580 } 581 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 582 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 583 goto err1; 584 } 585 if (gelf_getehdr(e, &ehdr) == NULL) { 586 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); 587 goto err2; 588 } 589 /* 590 * Find the section we are looking for. 591 */ 592 scn = NULL; 593 while ((scn = elf_nextscn(e, scn)) != NULL) { 594 gelf_getshdr(scn, &shdr); 595 if (which == PR_SYMTAB && 596 shdr.sh_type == SHT_SYMTAB) { 597 foundscn = scn; 598 break; 599 } else if (which == PR_DYNSYM && 600 shdr.sh_type == SHT_DYNSYM) { 601 foundscn = scn; 602 break; 603 } 604 } 605 if (!foundscn) 606 return (-1); 607 stridx = shdr.sh_link; 608 if ((data = elf_getdata(foundscn, NULL)) == NULL) { 609 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); 610 goto err2; 611 } 612 for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) { 613 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL && 614 (mask & BIND_LOCAL) == 0) 615 continue; 616 if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL && 617 (mask & BIND_GLOBAL) == 0) 618 continue; 619 if (GELF_ST_BIND(sym.st_info) == STB_WEAK && 620 (mask & BIND_WEAK) == 0) 621 continue; 622 if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE && 623 (mask & TYPE_NOTYPE) == 0) 624 continue; 625 if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT && 626 (mask & TYPE_OBJECT) == 0) 627 continue; 628 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC && 629 (mask & TYPE_FUNC) == 0) 630 continue; 631 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && 632 (mask & TYPE_SECTION) == 0) 633 continue; 634 if (GELF_ST_TYPE(sym.st_info) == STT_FILE && 635 (mask & TYPE_FILE) == 0) 636 continue; 637 s = elf_strptr(e, stridx, sym.st_name); 638 if (ehdr.e_type != ET_EXEC) 639 sym.st_value += map->pr_vaddr; 640 if ((error = (*func)(cd, &sym, s)) != 0) 641 goto err2; 642 } 643 error = 0; 644 err2: 645 elf_end(e); 646 err1: 647 close(fd); 648 err0: 649 free(map); 650 return (error); 651 } 652