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