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