1 /*- 2 * Copyright (c) 2016 Mark Johnston <markj@FreeBSD.org> 3 * Copyright (c) 2010 The FreeBSD Foundation 4 * Copyright (c) 2008 John Birrell (jb@freebsd.org) 5 * All rights reserved. 6 * 7 * Portions of this software were developed by Rui Paulo under sponsorship 8 * from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/types.h> 36 #ifndef NO_CTF 37 #include <sys/ctf.h> 38 #include <sys/ctf_api.h> 39 #endif 40 #include <sys/user.h> 41 42 #include <assert.h> 43 #include <err.h> 44 #include <fcntl.h> 45 #include <libgen.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 #ifndef NO_CTF 51 #include <libctf.h> 52 #endif 53 #include <libutil.h> 54 55 #include "crc32.h" 56 #include "_libproc.h" 57 58 #define PATH_DEBUG_DIR "/usr/lib/debug" 59 60 #ifdef NO_CTF 61 typedef struct ctf_file ctf_file_t; 62 #endif 63 64 #ifndef NO_CXA_DEMANGLE 65 extern char *__cxa_demangle(const char *, char *, size_t *, int *); 66 #endif /* NO_CXA_DEMANGLE */ 67 68 static int 69 crc32_file(int fd, uint32_t *crc) 70 { 71 uint8_t buf[PAGE_SIZE], *p; 72 size_t n; 73 74 *crc = ~0; 75 while ((n = read(fd, buf, sizeof(buf))) > 0) { 76 p = &buf[0]; 77 while (n-- > 0) 78 *crc = crc32_tab[(*crc ^ *p++) & 0xff] ^ (*crc >> 8); 79 } 80 *crc = ~*crc; 81 return (n); 82 } 83 84 static void 85 demangle(const char *symbol, char *buf, size_t len) 86 { 87 #ifndef NO_CXA_DEMANGLE 88 char *dembuf; 89 90 if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) { 91 dembuf = __cxa_demangle(symbol, NULL, NULL, NULL); 92 if (!dembuf) 93 goto fail; 94 strlcpy(buf, dembuf, len); 95 free(dembuf); 96 return; 97 } 98 fail: 99 #endif /* NO_CXA_DEMANGLE */ 100 strlcpy(buf, symbol, len); 101 } 102 103 static int 104 symvalcomp(void *thunk, const void *a1, const void *a2) 105 { 106 struct symtab *symtab; 107 GElf_Sym sym1, sym2; 108 u_int i1, i2; 109 int ret; 110 111 i1 = *(const u_int *)a1; 112 i2 = *(const u_int *)a2; 113 symtab = thunk; 114 115 (void)gelf_getsym(symtab->data, i1, &sym1); 116 (void)gelf_getsym(symtab->data, i2, &sym2); 117 if (sym1.st_value < sym2.st_value) 118 ret = -1; 119 else if (sym1.st_value == sym2.st_value) 120 ret = 0; 121 else 122 ret = 1; 123 return (ret); 124 } 125 126 static int 127 load_symtab(Elf *e, struct symtab *symtab, u_long sh_type) 128 { 129 GElf_Ehdr ehdr; 130 GElf_Shdr shdr; 131 Elf_Scn *scn; 132 u_int nsyms; 133 134 if (gelf_getehdr(e, &ehdr) == NULL) 135 return (-1); 136 137 scn = NULL; 138 while ((scn = elf_nextscn(e, scn)) != NULL) { 139 (void)gelf_getshdr(scn, &shdr); 140 if (shdr.sh_type == sh_type) 141 break; 142 } 143 if (scn == NULL) 144 return (-1); 145 146 nsyms = shdr.sh_size / shdr.sh_entsize; 147 if (nsyms > (1 << 20)) 148 return (-1); 149 150 if ((symtab->data = elf_getdata(scn, NULL)) == NULL) 151 return (-1); 152 153 symtab->index = calloc(nsyms, sizeof(u_int)); 154 if (symtab->index == NULL) 155 return (-1); 156 for (u_int i = 0; i < nsyms; i++) 157 symtab->index[i] = i; 158 qsort_r(symtab->index, nsyms, sizeof(u_int), symtab, symvalcomp); 159 symtab->nsyms = nsyms; 160 symtab->stridx = shdr.sh_link; 161 return (0); 162 } 163 164 static void 165 load_symtabs(struct file_info *file) 166 { 167 168 file->symtab.nsyms = file->dynsymtab.nsyms = 0; 169 (void)load_symtab(file->elf, &file->symtab, SHT_SYMTAB); 170 (void)load_symtab(file->elf, &file->dynsymtab, SHT_DYNSYM); 171 } 172 173 static int 174 open_debug_file(char *path, const char *debugfile, uint32_t crc) 175 { 176 size_t n; 177 uint32_t compcrc; 178 int fd; 179 180 fd = -1; 181 if ((n = strlcat(path, "/", PATH_MAX)) >= PATH_MAX) 182 return (fd); 183 if (strlcat(path, debugfile, PATH_MAX) >= PATH_MAX) 184 goto out; 185 if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) 186 goto out; 187 if (crc32_file(fd, &compcrc) != 0 || crc != compcrc) { 188 DPRINTFX("ERROR: CRC32 mismatch for %s", path); 189 (void)close(fd); 190 fd = -1; 191 } 192 out: 193 path[n] = '\0'; 194 return (fd); 195 } 196 197 /* 198 * Obtain an ELF descriptor for the specified mapped object. If a GNU debuglink 199 * section is present, a descriptor for the corresponding debug file is 200 * returned. 201 */ 202 static int 203 open_object(struct map_info *mapping) 204 { 205 char path[PATH_MAX]; 206 GElf_Shdr shdr; 207 Elf *e, *e2; 208 Elf_Data *data; 209 Elf_Scn *scn; 210 struct file_info *file; 211 prmap_t *map; 212 const char *debugfile, *scnname; 213 size_t ndx; 214 uint32_t crc; 215 int fd, fd2; 216 217 if (mapping->map.pr_mapname[0] == '\0') 218 return (-1); /* anonymous object */ 219 if (mapping->file->elf != NULL) 220 return (0); /* already loaded */ 221 222 file = mapping->file; 223 map = &mapping->map; 224 if ((fd = open(map->pr_mapname, O_RDONLY | O_CLOEXEC)) < 0) { 225 DPRINTF("ERROR: open %s failed", map->pr_mapname); 226 return (-1); 227 } 228 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 229 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1)); 230 goto err; 231 } 232 if (gelf_getehdr(e, &file->ehdr) != &file->ehdr) { 233 DPRINTFX("ERROR: elf_getehdr() failed: %s", elf_errmsg(-1)); 234 goto err; 235 } 236 237 scn = NULL; 238 while ((scn = elf_nextscn(e, scn)) != NULL) { 239 if (gelf_getshdr(scn, &shdr) != &shdr) { 240 DPRINTFX("ERROR: gelf_getshdr failed: %s", 241 elf_errmsg(-1)); 242 goto err; 243 } 244 if (shdr.sh_type != SHT_PROGBITS) 245 continue; 246 if (elf_getshdrstrndx(e, &ndx) != 0) { 247 DPRINTFX("ERROR: elf_getshdrstrndx failed: %s", 248 elf_errmsg(-1)); 249 goto err; 250 } 251 if ((scnname = elf_strptr(e, ndx, shdr.sh_name)) == NULL) 252 continue; 253 254 if (strcmp(scnname, ".gnu_debuglink") == 0) 255 break; 256 } 257 if (scn == NULL) 258 goto internal; 259 260 if ((data = elf_getdata(scn, NULL)) == NULL) { 261 DPRINTFX("ERROR: elf_getdata failed: %s", elf_errmsg(-1)); 262 goto err; 263 } 264 265 /* 266 * The data contains a null-terminated file name followed by a 4-byte 267 * CRC. 268 */ 269 if (data->d_size < sizeof(crc) + 1) { 270 DPRINTFX("ERROR: debuglink section is too small (%zd bytes)", 271 data->d_size); 272 goto internal; 273 } 274 if (strnlen(data->d_buf, data->d_size) >= data->d_size - sizeof(crc)) { 275 DPRINTFX("ERROR: no null-terminator in gnu_debuglink section"); 276 goto internal; 277 } 278 279 debugfile = data->d_buf; 280 memcpy(&crc, (char *)data->d_buf + data->d_size - sizeof(crc), 281 sizeof(crc)); 282 283 /* 284 * Search for the debug file using the algorithm described in the gdb 285 * documentation: 286 * - look in the directory containing the object, 287 * - look in the subdirectory ".debug" of the directory containing the 288 * object, 289 * - look in the global debug directories (currently /usr/lib/debug). 290 */ 291 (void)strlcpy(path, map->pr_mapname, sizeof(path)); 292 (void)dirname(path); 293 294 if ((fd2 = open_debug_file(path, debugfile, crc)) >= 0) 295 goto external; 296 297 if (strlcat(path, "/.debug", sizeof(path)) < sizeof(path) && 298 (fd2 = open_debug_file(path, debugfile, crc)) >= 0) 299 goto external; 300 301 (void)snprintf(path, sizeof(path), PATH_DEBUG_DIR); 302 if (strlcat(path, map->pr_mapname, sizeof(path)) < sizeof(path)) { 303 (void)dirname(path); 304 if ((fd2 = open_debug_file(path, debugfile, crc)) >= 0) 305 goto external; 306 } 307 308 internal: 309 /* We didn't find a debug file, just return the object's descriptor. */ 310 file->elf = e; 311 file->fd = fd; 312 load_symtabs(file); 313 return (0); 314 315 external: 316 if ((e2 = elf_begin(fd2, ELF_C_READ, NULL)) == NULL) { 317 DPRINTFX("ERROR: elf_begin failed: %s", elf_errmsg(-1)); 318 (void)close(fd2); 319 goto err; 320 } 321 (void)elf_end(e); 322 (void)close(fd); 323 file->elf = e2; 324 file->fd = fd2; 325 load_symtabs(file); 326 return (0); 327 328 err: 329 if (e != NULL) 330 (void)elf_end(e); 331 (void)close(fd); 332 return (-1); 333 } 334 335 char * 336 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname, 337 size_t objnamesz) 338 { 339 prmap_t *map; 340 size_t i; 341 342 if (p->nmappings == 0) 343 if (proc_rdagent(p) == NULL) 344 return (NULL); 345 for (i = 0; i < p->nmappings; i++) { 346 map = &p->mappings[i].map; 347 if (addr >= map->pr_vaddr && 348 addr < map->pr_vaddr + map->pr_size) { 349 strlcpy(objname, map->pr_mapname, objnamesz); 350 return (objname); 351 } 352 } 353 return (NULL); 354 } 355 356 int 357 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd) 358 { 359 char last[MAXPATHLEN], path[MAXPATHLEN], *base; 360 prmap_t *map; 361 size_t i; 362 int error; 363 364 if (p->nmappings == 0) 365 if (proc_rdagent(p) == NULL) 366 return (-1); 367 368 error = 0; 369 memset(last, 0, sizeof(last)); 370 for (i = 0; i < p->nmappings; i++) { 371 map = &p->mappings[i].map; 372 strlcpy(path, map->pr_mapname, sizeof(path)); 373 base = basename(path); 374 /* 375 * We shouldn't call the callback twice with the same object. 376 * To do that we are assuming the fact that if there are 377 * repeated object names (i.e. different mappings for the 378 * same object) they occur next to each other. 379 */ 380 if (strcmp(base, last) == 0) 381 continue; 382 if ((error = (*func)(cd, map, base)) != 0) 383 break; 384 strlcpy(last, path, sizeof(last)); 385 } 386 return (error); 387 } 388 389 static struct map_info * 390 _proc_addr2map(struct proc_handle *p, uintptr_t addr) 391 { 392 struct map_info *mapping; 393 size_t i; 394 395 if (p->nmappings == 0) 396 if (proc_rdagent(p) == NULL) 397 return (NULL); 398 for (i = 0; i < p->nmappings; i++) { 399 mapping = &p->mappings[i]; 400 if (addr >= mapping->map.pr_vaddr && 401 addr < mapping->map.pr_vaddr + mapping->map.pr_size) 402 return (mapping); 403 } 404 return (NULL); 405 } 406 407 prmap_t * 408 proc_addr2map(struct proc_handle *p, uintptr_t addr) 409 { 410 411 return (&_proc_addr2map(p, addr)->map); 412 } 413 414 /* 415 * Look up the symbol at addr using a binary search, returning a copy of the 416 * symbol and its name. 417 */ 418 static int 419 lookup_symbol_by_addr(Elf *elf, struct symtab *symtab, uintptr_t addr, 420 const char **namep, GElf_Sym *sym) 421 { 422 Elf_Data *data; 423 const char *s; 424 int min, max, mid; 425 426 data = symtab->data; 427 min = 0; 428 max = symtab->nsyms - 1; 429 430 while (min <= max) { 431 mid = (max + min) / 2; 432 (void)gelf_getsym(data, symtab->index[mid], sym); 433 if (addr >= sym->st_value && 434 addr < sym->st_value + sym->st_size) { 435 s = elf_strptr(elf, symtab->stridx, sym->st_name); 436 if (s != NULL && namep != NULL) 437 *namep = s; 438 return (0); 439 } 440 441 if (addr < sym->st_value) 442 max = mid - 1; 443 else 444 min = mid + 1; 445 } 446 return (ENOENT); 447 } 448 449 int 450 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name, 451 size_t namesz, GElf_Sym *symcopy) 452 { 453 struct file_info *file; 454 struct map_info *mapping; 455 const char *s; 456 uintptr_t off; 457 int error; 458 459 if ((mapping = _proc_addr2map(p, addr)) == NULL) { 460 DPRINTFX("ERROR: proc_addr2map failed to resolve 0x%jx", addr); 461 return (-1); 462 } 463 if (open_object(mapping) != 0) { 464 DPRINTFX("ERROR: failed to open object %s", 465 mapping->map.pr_mapname); 466 return (-1); 467 } 468 469 file = mapping->file; 470 off = file->ehdr.e_type == ET_DYN ? mapping->map.pr_vaddr : 0; 471 if (addr < off) 472 return (ENOENT); 473 addr -= off; 474 475 error = lookup_symbol_by_addr(file->elf, &file->dynsymtab, addr, &s, 476 symcopy); 477 if (error == ENOENT) 478 error = lookup_symbol_by_addr(file->elf, &file->symtab, addr, 479 &s, symcopy); 480 if (error == 0) { 481 symcopy->st_value += off; 482 demangle(s, name, namesz); 483 } 484 return (error); 485 } 486 487 static struct map_info * 488 _proc_name2map(struct proc_handle *p, const char *name) 489 { 490 char path[MAXPATHLEN], *base; 491 struct map_info *mapping; 492 size_t i, len; 493 494 if ((len = strlen(name)) == 0) 495 return (NULL); 496 if (p->nmappings == 0) 497 if (proc_rdagent(p) == NULL) 498 return (NULL); 499 for (i = 0; i < p->nmappings; i++) { 500 mapping = &p->mappings[i]; 501 (void)strlcpy(path, mapping->map.pr_mapname, sizeof(path)); 502 base = basename(path); 503 if (strcmp(base, name) == 0) 504 return (mapping); 505 } 506 /* If we didn't find a match, try matching prefixes of the basename. */ 507 for (i = 0; i < p->nmappings; i++) { 508 strlcpy(path, p->mappings[i].map.pr_mapname, sizeof(path)); 509 base = basename(path); 510 if (strncmp(base, name, len) == 0) 511 return (&p->mappings[i]); 512 } 513 if (strcmp(name, "a.out") == 0) 514 return (_proc_addr2map(p, 515 p->mappings[p->exec_map].map.pr_vaddr)); 516 return (NULL); 517 } 518 519 prmap_t * 520 proc_name2map(struct proc_handle *p, const char *name) 521 { 522 523 return (&_proc_name2map(p, name)->map); 524 } 525 526 /* 527 * Look up the symbol with the given name and return a copy of it. 528 */ 529 static int 530 lookup_symbol_by_name(Elf *elf, struct symtab *symtab, const char *symbol, 531 GElf_Sym *symcopy, prsyminfo_t *si) 532 { 533 GElf_Sym sym; 534 Elf_Data *data; 535 char *s; 536 int i; 537 538 if (symtab->nsyms == 0) 539 return (ENOENT); 540 data = symtab->data; 541 for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) { 542 s = elf_strptr(elf, symtab->stridx, sym.st_name); 543 if (s != NULL && strcmp(s, symbol) == 0) { 544 memcpy(symcopy, &sym, sizeof(*symcopy)); 545 if (si != NULL) 546 si->prs_id = i; 547 return (0); 548 } 549 } 550 return (ENOENT); 551 } 552 553 int 554 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol, 555 GElf_Sym *symcopy, prsyminfo_t *si) 556 { 557 struct file_info *file; 558 struct map_info *mapping; 559 uintptr_t off; 560 int error; 561 562 if ((mapping = _proc_name2map(p, object)) == NULL) { 563 DPRINTFX("ERROR: proc_name2map failed to resolve %s", object); 564 return (-1); 565 } 566 if (open_object(mapping) != 0) { 567 DPRINTFX("ERROR: failed to open object %s", 568 mapping->map.pr_mapname); 569 return (-1); 570 } 571 572 file = mapping->file; 573 off = file->ehdr.e_type == ET_DYN ? mapping->map.pr_vaddr : 0; 574 575 error = lookup_symbol_by_name(file->elf, &file->dynsymtab, symbol, 576 symcopy, si); 577 if (error == ENOENT) 578 error = lookup_symbol_by_name(file->elf, &file->symtab, symbol, 579 symcopy, si); 580 if (error == 0) 581 symcopy->st_value += off; 582 return (error); 583 } 584 585 ctf_file_t * 586 proc_name2ctf(struct proc_handle *p, const char *name) 587 { 588 #ifndef NO_CTF 589 ctf_file_t *ctf; 590 prmap_t *map; 591 int error; 592 593 if ((map = proc_name2map(p, name)) == NULL) 594 return (NULL); 595 596 ctf = ctf_open(map->pr_mapname, &error); 597 return (ctf); 598 #else 599 (void)p; 600 (void)name; 601 return (NULL); 602 #endif 603 } 604 605 int 606 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which, 607 int mask, proc_sym_f *func, void *cd) 608 { 609 GElf_Sym sym; 610 struct file_info *file; 611 struct map_info *mapping; 612 struct symtab *symtab; 613 const char *s; 614 int error, i; 615 616 if ((mapping = _proc_name2map(p, object)) == NULL) { 617 DPRINTFX("ERROR: proc_name2map failed to resolve %s", object); 618 return (-1); 619 } 620 if (open_object(mapping) != 0) { 621 DPRINTFX("ERROR: failed to open object %s", 622 mapping->map.pr_mapname); 623 return (-1); 624 } 625 626 file = mapping->file; 627 symtab = which == PR_SYMTAB ? &file->symtab : &file->dynsymtab; 628 if (symtab->nsyms == 0) 629 return (-1); 630 631 error = 0; 632 for (i = 0; gelf_getsym(symtab->data, i, &sym) != NULL; i++) { 633 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL && 634 (mask & BIND_LOCAL) == 0) 635 continue; 636 if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL && 637 (mask & BIND_GLOBAL) == 0) 638 continue; 639 if (GELF_ST_BIND(sym.st_info) == STB_WEAK && 640 (mask & BIND_WEAK) == 0) 641 continue; 642 if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE && 643 (mask & TYPE_NOTYPE) == 0) 644 continue; 645 if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT && 646 (mask & TYPE_OBJECT) == 0) 647 continue; 648 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC && 649 (mask & TYPE_FUNC) == 0) 650 continue; 651 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && 652 (mask & TYPE_SECTION) == 0) 653 continue; 654 if (GELF_ST_TYPE(sym.st_info) == STT_FILE && 655 (mask & TYPE_FILE) == 0) 656 continue; 657 s = elf_strptr(file->elf, symtab->stridx, sym.st_name); 658 if (file->ehdr.e_type == ET_DYN) 659 sym.st_value += mapping->map.pr_vaddr; 660 if ((error = (*func)(cd, &sym, s)) != 0) 661 break; 662 } 663 return (error); 664 } 665