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