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