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