1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stddef.h> 32 #include <unistd.h> 33 #include <ctype.h> 34 #include <fcntl.h> 35 #include <string.h> 36 #include <strings.h> 37 #include <memory.h> 38 #include <errno.h> 39 #include <dirent.h> 40 #include <signal.h> 41 #include <limits.h> 42 #include <libgen.h> 43 #include <zone.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <sys/systeminfo.h> 47 #include <sys/sysmacros.h> 48 49 #include "libproc.h" 50 #include "Pcontrol.h" 51 #include "Putil.h" 52 53 static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *); 54 static map_info_t *exec_map(struct ps_prochandle *); 55 static map_info_t *object_to_map(struct ps_prochandle *, Lmid_t, const char *); 56 static map_info_t *object_name_to_map(struct ps_prochandle *, 57 Lmid_t, const char *); 58 static GElf_Sym *sym_by_name(sym_tbl_t *, const char *, GElf_Sym *, uint_t *); 59 static int read_ehdr32(struct ps_prochandle *, Elf32_Ehdr *, uint_t *, 60 uintptr_t); 61 #ifdef _LP64 62 static int read_ehdr64(struct ps_prochandle *, Elf64_Ehdr *, uint_t *, 63 uintptr_t); 64 #endif 65 66 #define DATA_TYPES \ 67 ((1 << STT_OBJECT) | (1 << STT_FUNC) | \ 68 (1 << STT_COMMON) | (1 << STT_TLS)) 69 #define IS_DATA_TYPE(tp) (((1 << (tp)) & DATA_TYPES) != 0) 70 71 #define MA_RWX (MA_READ | MA_WRITE | MA_EXEC) 72 73 typedef enum { 74 PRO_NATURAL, 75 PRO_BYADDR, 76 PRO_BYNAME 77 } pr_order_t; 78 79 static int 80 addr_cmp(const void *aa, const void *bb) 81 { 82 uintptr_t a = *((uintptr_t *)aa); 83 uintptr_t b = *((uintptr_t *)bb); 84 85 if (a > b) 86 return (1); 87 if (a < b) 88 return (-1); 89 return (0); 90 } 91 92 /* 93 * Allocation function for a new file_info_t 94 */ 95 static file_info_t * 96 file_info_new(struct ps_prochandle *P, map_info_t *mptr) 97 { 98 file_info_t *fptr; 99 map_info_t *mp; 100 uintptr_t a, addr, *addrs, last = 0; 101 uint_t i, j, naddrs = 0, unordered = 0; 102 103 if ((fptr = calloc(1, sizeof (file_info_t))) == NULL) 104 return (NULL); 105 106 list_link(fptr, &P->file_head); 107 (void) strcpy(fptr->file_pname, mptr->map_pmap.pr_mapname); 108 mptr->map_file = fptr; 109 fptr->file_ref = 1; 110 fptr->file_fd = -1; 111 P->num_files++; 112 113 /* 114 * To figure out which map_info_t instances correspond to the mappings 115 * for this load object, we look at the in-memory ELF image in the 116 * base mapping (usually the program text). We examine the program 117 * headers to find the addresses at the beginning and end of each 118 * section and store them in a list which we then sort. Finally, we 119 * walk down the list of addresses and the list of map_info_t 120 * instances in lock step to correctly find the mappings that 121 * correspond to this load object. 122 */ 123 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 124 Elf32_Ehdr ehdr; 125 Elf32_Phdr phdr; 126 uint_t phnum; 127 128 if (read_ehdr32(P, &ehdr, &phnum, mptr->map_pmap.pr_vaddr) != 0) 129 return (fptr); 130 131 addrs = malloc(sizeof (uintptr_t) * phnum * 2); 132 a = mptr->map_pmap.pr_vaddr + ehdr.e_phoff; 133 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) { 134 if (Pread(P, &phdr, sizeof (phdr), a) != sizeof (phdr)) 135 goto out; 136 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0) 137 continue; 138 139 addr = phdr.p_vaddr; 140 if (ehdr.e_type == ET_DYN) 141 addr += mptr->map_pmap.pr_vaddr; 142 if (last > addr) 143 unordered = 1; 144 addrs[naddrs++] = addr; 145 addrs[naddrs++] = last = addr + phdr.p_memsz - 1; 146 } 147 #ifdef _LP64 148 } else { 149 Elf64_Ehdr ehdr; 150 Elf64_Phdr phdr; 151 uint_t phnum; 152 153 if (read_ehdr64(P, &ehdr, &phnum, mptr->map_pmap.pr_vaddr) != 0) 154 return (fptr); 155 156 addrs = malloc(sizeof (uintptr_t) * phnum * 2); 157 a = mptr->map_pmap.pr_vaddr + ehdr.e_phoff; 158 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) { 159 if (Pread(P, &phdr, sizeof (phdr), a) != sizeof (phdr)) 160 goto out; 161 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0) 162 continue; 163 164 addr = phdr.p_vaddr; 165 if (ehdr.e_type == ET_DYN) 166 addr += mptr->map_pmap.pr_vaddr; 167 if (last > addr) 168 unordered = 1; 169 addrs[naddrs++] = addr; 170 addrs[naddrs++] = last = addr + phdr.p_memsz - 1; 171 } 172 #endif 173 } 174 175 if (unordered) 176 qsort(addrs, naddrs, sizeof (uintptr_t), addr_cmp); 177 178 179 i = j = 0; 180 mp = P->mappings; 181 while (j < P->map_count && i < naddrs) { 182 addr = addrs[i]; 183 if (addr >= mp->map_pmap.pr_vaddr && 184 addr < mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size && 185 mp->map_file == NULL) { 186 mp->map_file = fptr; 187 fptr->file_ref++; 188 } 189 190 if (addr < mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size) { 191 i++; 192 } else { 193 mp++; 194 j++; 195 } 196 } 197 198 out: 199 free(addrs); 200 return (fptr); 201 } 202 203 /* 204 * Deallocation function for a file_info_t 205 */ 206 static void 207 file_info_free(struct ps_prochandle *P, file_info_t *fptr) 208 { 209 if (--fptr->file_ref == 0) { 210 list_unlink(fptr); 211 if (fptr->file_symtab.sym_elf) { 212 (void) elf_end(fptr->file_symtab.sym_elf); 213 free(fptr->file_symtab.sym_elfmem); 214 } 215 if (fptr->file_symtab.sym_byname) 216 free(fptr->file_symtab.sym_byname); 217 if (fptr->file_symtab.sym_byaddr) 218 free(fptr->file_symtab.sym_byaddr); 219 220 if (fptr->file_dynsym.sym_elf) { 221 (void) elf_end(fptr->file_dynsym.sym_elf); 222 free(fptr->file_dynsym.sym_elfmem); 223 } 224 if (fptr->file_dynsym.sym_byname) 225 free(fptr->file_dynsym.sym_byname); 226 if (fptr->file_dynsym.sym_byaddr) 227 free(fptr->file_dynsym.sym_byaddr); 228 229 if (fptr->file_lo) 230 free(fptr->file_lo); 231 if (fptr->file_lname) 232 free(fptr->file_lname); 233 if (fptr->file_elf) 234 (void) elf_end(fptr->file_elf); 235 if (fptr->file_elfmem != NULL) 236 free(fptr->file_elfmem); 237 if (fptr->file_fd >= 0) 238 (void) close(fptr->file_fd); 239 if (fptr->file_ctfp) { 240 ctf_close(fptr->file_ctfp); 241 free(fptr->file_ctf_buf); 242 } 243 free(fptr); 244 P->num_files--; 245 } 246 } 247 248 /* 249 * Deallocation function for a map_info_t 250 */ 251 static void 252 map_info_free(struct ps_prochandle *P, map_info_t *mptr) 253 { 254 file_info_t *fptr; 255 256 if ((fptr = mptr->map_file) != NULL) { 257 if (fptr->file_map == mptr) 258 fptr->file_map = NULL; 259 file_info_free(P, fptr); 260 } 261 if (P->execname && mptr == P->map_exec) { 262 free(P->execname); 263 P->execname = NULL; 264 } 265 if (P->auxv && (mptr == P->map_exec || mptr == P->map_ldso)) { 266 free(P->auxv); 267 P->auxv = NULL; 268 P->nauxv = 0; 269 } 270 if (mptr == P->map_exec) 271 P->map_exec = NULL; 272 if (mptr == P->map_ldso) 273 P->map_ldso = NULL; 274 } 275 276 /* 277 * Call-back function for librtld_db to iterate through all of its shared 278 * libraries. We use this to get the load object names for the mappings. 279 */ 280 static int 281 map_iter(const rd_loadobj_t *lop, void *cd) 282 { 283 char buf[PATH_MAX]; 284 struct ps_prochandle *P = cd; 285 map_info_t *mptr; 286 file_info_t *fptr; 287 288 dprintf("encountered rd object at %p\n", (void *)lop->rl_base); 289 290 if ((mptr = Paddr2mptr(P, lop->rl_base)) == NULL) 291 return (1); /* Base address does not match any mapping */ 292 293 if ((fptr = mptr->map_file) == NULL && 294 (fptr = file_info_new(P, mptr)) == NULL) 295 return (1); /* Failed to allocate a new file_info_t */ 296 297 if ((fptr->file_lo == NULL) && 298 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) { 299 file_info_free(P, fptr); 300 return (1); /* Failed to allocate rd_loadobj_t */ 301 } 302 303 fptr->file_map = mptr; 304 *fptr->file_lo = *lop; 305 306 fptr->file_lo->rl_plt_base = fptr->file_plt_base; 307 fptr->file_lo->rl_plt_size = fptr->file_plt_size; 308 309 if (fptr->file_lname) { 310 free(fptr->file_lname); 311 fptr->file_lname = NULL; 312 } 313 314 if (Pread_string(P, buf, sizeof (buf), lop->rl_nameaddr) > 0) { 315 if ((fptr->file_lname = strdup(buf)) != NULL) 316 fptr->file_lbase = basename(fptr->file_lname); 317 } 318 319 dprintf("loaded rd object %s lmid %lx\n", 320 fptr->file_lname ? fptr->file_lname : "<NULL>", lop->rl_lmident); 321 return (1); 322 } 323 324 static void 325 map_set(struct ps_prochandle *P, map_info_t *mptr, const char *lname) 326 { 327 file_info_t *fptr; 328 329 if ((fptr = mptr->map_file) == NULL && 330 (fptr = file_info_new(P, mptr)) == NULL) 331 return; /* Failed to allocate a new file_info_t */ 332 333 fptr->file_map = mptr; 334 335 if ((fptr->file_lo == NULL) && 336 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) { 337 file_info_free(P, fptr); 338 return; /* Failed to allocate rd_loadobj_t */ 339 } 340 341 (void) memset(fptr->file_lo, 0, sizeof (rd_loadobj_t)); 342 fptr->file_lo->rl_base = mptr->map_pmap.pr_vaddr; 343 fptr->file_lo->rl_bend = 344 mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size; 345 346 fptr->file_lo->rl_plt_base = fptr->file_plt_base; 347 fptr->file_lo->rl_plt_size = fptr->file_plt_size; 348 349 if (fptr->file_lname) { 350 free(fptr->file_lname); 351 fptr->file_lname = NULL; 352 } 353 354 if ((fptr->file_lname = strdup(lname)) != NULL) 355 fptr->file_lbase = basename(fptr->file_lname); 356 } 357 358 static void 359 load_static_maps(struct ps_prochandle *P) 360 { 361 map_info_t *mptr; 362 363 /* 364 * Construct the map for the a.out. 365 */ 366 if ((mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_EXEC)) != NULL) 367 map_set(P, mptr, "a.out"); 368 369 /* 370 * If the dynamic linker exists for this process, 371 * construct the map for it. 372 */ 373 if (Pgetauxval(P, AT_BASE) != -1L && 374 (mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_LDSO)) != NULL) 375 map_set(P, mptr, "ld.so.1"); 376 } 377 378 /* 379 * Go through all the address space mappings, validating or updating 380 * the information already gathered, or gathering new information. 381 * 382 * This function is only called when we suspect that the mappings have changed 383 * because this is the first time we're calling it or because of rtld activity. 384 */ 385 void 386 Pupdate_maps(struct ps_prochandle *P) 387 { 388 char mapfile[64]; 389 int mapfd; 390 struct stat statb; 391 prmap_t *Pmap = NULL; 392 prmap_t *pmap; 393 ssize_t nmap; 394 int i; 395 uint_t oldmapcount; 396 map_info_t *newmap, *newp; 397 map_info_t *mptr; 398 399 if (P->info_valid || P->state == PS_UNDEAD) 400 return; 401 402 Preadauxvec(P); 403 404 (void) sprintf(mapfile, "/proc/%d/map", (int)P->pid); 405 if ((mapfd = open(mapfile, O_RDONLY)) < 0 || 406 fstat(mapfd, &statb) != 0 || 407 statb.st_size < sizeof (prmap_t) || 408 (Pmap = malloc(statb.st_size)) == NULL || 409 (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 || 410 (nmap /= sizeof (prmap_t)) == 0) { 411 if (Pmap != NULL) 412 free(Pmap); 413 if (mapfd >= 0) 414 (void) close(mapfd); 415 Preset_maps(P); /* utter failure; destroy tables */ 416 return; 417 } 418 (void) close(mapfd); 419 420 if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL) 421 return; 422 423 /* 424 * We try to merge any file information we may have for existing 425 * mappings, to avoid having to rebuild the file info. 426 */ 427 mptr = P->mappings; 428 pmap = Pmap; 429 newp = newmap; 430 oldmapcount = P->map_count; 431 for (i = 0; i < nmap; i++, pmap++, newp++) { 432 433 if (oldmapcount == 0) { 434 /* 435 * We've exhausted all the old mappings. Every new 436 * mapping should be added. 437 */ 438 newp->map_pmap = *pmap; 439 440 } else if (pmap->pr_vaddr == mptr->map_pmap.pr_vaddr && 441 pmap->pr_size == mptr->map_pmap.pr_size && 442 pmap->pr_offset == mptr->map_pmap.pr_offset && 443 (pmap->pr_mflags & ~(MA_BREAK | MA_STACK)) == 444 (mptr->map_pmap.pr_mflags & ~(MA_BREAK | MA_STACK)) && 445 pmap->pr_pagesize == mptr->map_pmap.pr_pagesize && 446 pmap->pr_shmid == mptr->map_pmap.pr_shmid && 447 strcmp(pmap->pr_mapname, mptr->map_pmap.pr_mapname) == 0) { 448 449 /* 450 * This mapping matches exactly. Copy over the old 451 * mapping, taking care to get the latest flags. 452 * Make sure the associated file_info_t is updated 453 * appropriately. 454 */ 455 *newp = *mptr; 456 if (P->map_exec == mptr) 457 P->map_exec = newp; 458 if (P->map_ldso == mptr) 459 P->map_ldso = newp; 460 newp->map_pmap.pr_mflags = pmap->pr_mflags; 461 if (mptr->map_file != NULL && 462 mptr->map_file->file_map == mptr) 463 mptr->map_file->file_map = newp; 464 oldmapcount--; 465 mptr++; 466 467 } else if (pmap->pr_vaddr + pmap->pr_size > 468 mptr->map_pmap.pr_vaddr) { 469 470 /* 471 * The old mapping doesn't exist any more, remove it 472 * from the list. 473 */ 474 map_info_free(P, mptr); 475 oldmapcount--; 476 i--; 477 newp--; 478 pmap--; 479 mptr++; 480 481 } else { 482 483 /* 484 * This is a new mapping, add it directly. 485 */ 486 newp->map_pmap = *pmap; 487 } 488 } 489 490 /* 491 * Free any old maps 492 */ 493 while (oldmapcount) { 494 map_info_free(P, mptr); 495 oldmapcount--; 496 mptr++; 497 } 498 499 free(Pmap); 500 if (P->mappings != NULL) 501 free(P->mappings); 502 P->mappings = newmap; 503 P->map_count = P->map_alloc = nmap; 504 P->info_valid = 1; 505 506 /* 507 * Consult librtld_db to get the load object 508 * names for all of the shared libraries. 509 */ 510 if (P->rap != NULL) 511 (void) rd_loadobj_iter(P->rap, map_iter, P); 512 } 513 514 /* 515 * Update all of the mappings and rtld_db as if by Pupdate_maps(), and then 516 * forcibly cache all of the symbol tables associated with all object files. 517 */ 518 void 519 Pupdate_syms(struct ps_prochandle *P) 520 { 521 file_info_t *fptr = list_next(&P->file_head); 522 int i; 523 524 Pupdate_maps(P); 525 526 for (i = 0; i < P->num_files; i++, fptr = list_next(fptr)) { 527 Pbuild_file_symtab(P, fptr); 528 (void) Pbuild_file_ctf(P, fptr); 529 } 530 } 531 532 /* 533 * Return the librtld_db agent handle for the victim process. 534 * The handle will become invalid at the next successful exec() and the 535 * client (caller of proc_rd_agent()) must not use it beyond that point. 536 * If the process is already dead, we've already tried our best to 537 * create the agent during core file initialization. 538 */ 539 rd_agent_t * 540 Prd_agent(struct ps_prochandle *P) 541 { 542 if (P->rap == NULL && P->state != PS_DEAD && P->state != PS_IDLE) { 543 Pupdate_maps(P); 544 if (P->num_files == 0) 545 load_static_maps(P); 546 rd_log(_libproc_debug); 547 if ((P->rap = rd_new(P)) != NULL) 548 (void) rd_loadobj_iter(P->rap, map_iter, P); 549 } 550 return (P->rap); 551 } 552 553 /* 554 * Return the prmap_t structure containing 'addr', but only if it 555 * is in the dynamic linker's link map and is the text section. 556 */ 557 const prmap_t * 558 Paddr_to_text_map(struct ps_prochandle *P, uintptr_t addr) 559 { 560 map_info_t *mptr; 561 562 if (!P->info_valid) 563 Pupdate_maps(P); 564 565 if ((mptr = Paddr2mptr(P, addr)) != NULL) { 566 file_info_t *fptr = build_map_symtab(P, mptr); 567 const prmap_t *pmp = &mptr->map_pmap; 568 569 if (fptr != NULL && fptr->file_lo != NULL && 570 fptr->file_lo->rl_base >= pmp->pr_vaddr && 571 fptr->file_lo->rl_base < pmp->pr_vaddr + pmp->pr_size) 572 return (pmp); 573 } 574 575 return (NULL); 576 } 577 578 /* 579 * Return the prmap_t structure containing 'addr' (no restrictions on 580 * the type of mapping). 581 */ 582 const prmap_t * 583 Paddr_to_map(struct ps_prochandle *P, uintptr_t addr) 584 { 585 map_info_t *mptr; 586 587 if (!P->info_valid) 588 Pupdate_maps(P); 589 590 if ((mptr = Paddr2mptr(P, addr)) != NULL) 591 return (&mptr->map_pmap); 592 593 return (NULL); 594 } 595 596 /* 597 * Convert a full or partial load object name to the prmap_t for its 598 * corresponding primary text mapping. 599 */ 600 const prmap_t * 601 Plmid_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name) 602 { 603 map_info_t *mptr; 604 605 if (name == PR_OBJ_EVERY) 606 return (NULL); /* A reasonable mistake */ 607 608 if ((mptr = object_name_to_map(P, lmid, name)) != NULL) 609 return (&mptr->map_pmap); 610 611 return (NULL); 612 } 613 614 const prmap_t * 615 Pname_to_map(struct ps_prochandle *P, const char *name) 616 { 617 return (Plmid_to_map(P, PR_LMID_EVERY, name)); 618 } 619 620 const rd_loadobj_t * 621 Paddr_to_loadobj(struct ps_prochandle *P, uintptr_t addr) 622 { 623 map_info_t *mptr; 624 625 if (!P->info_valid) 626 Pupdate_maps(P); 627 628 if ((mptr = Paddr2mptr(P, addr)) == NULL) 629 return (NULL); 630 631 /* 632 * By building the symbol table, we implicitly bring the PLT 633 * information up to date in the load object. 634 */ 635 (void) build_map_symtab(P, mptr); 636 637 return (mptr->map_file->file_lo); 638 } 639 640 const rd_loadobj_t * 641 Plmid_to_loadobj(struct ps_prochandle *P, Lmid_t lmid, const char *name) 642 { 643 map_info_t *mptr; 644 645 if (name == PR_OBJ_EVERY) 646 return (NULL); 647 648 if ((mptr = object_name_to_map(P, lmid, name)) == NULL) 649 return (NULL); 650 651 /* 652 * By building the symbol table, we implicitly bring the PLT 653 * information up to date in the load object. 654 */ 655 (void) build_map_symtab(P, mptr); 656 657 return (mptr->map_file->file_lo); 658 } 659 660 const rd_loadobj_t * 661 Pname_to_loadobj(struct ps_prochandle *P, const char *name) 662 { 663 return (Plmid_to_loadobj(P, PR_LMID_EVERY, name)); 664 } 665 666 ctf_file_t * 667 Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr) 668 { 669 ctf_sect_t ctdata, symtab, strtab; 670 sym_tbl_t *symp; 671 int err; 672 673 if (fptr->file_ctfp != NULL) 674 return (fptr->file_ctfp); 675 676 Pbuild_file_symtab(P, fptr); 677 678 if (fptr->file_ctf_size == 0) 679 return (NULL); 680 681 symp = fptr->file_ctf_dyn ? &fptr->file_dynsym : &fptr->file_symtab; 682 if (symp->sym_data == NULL) 683 return (NULL); 684 685 /* 686 * The buffer may alread be allocated if this is a core file that 687 * contained CTF data for this file. 688 */ 689 if (fptr->file_ctf_buf == NULL) { 690 fptr->file_ctf_buf = malloc(fptr->file_ctf_size); 691 if (fptr->file_ctf_buf == NULL) { 692 dprintf("failed to allocate ctf buffer\n"); 693 return (NULL); 694 } 695 696 if (pread(fptr->file_fd, fptr->file_ctf_buf, 697 fptr->file_ctf_size, fptr->file_ctf_off) != 698 fptr->file_ctf_size) { 699 free(fptr->file_ctf_buf); 700 fptr->file_ctf_buf = NULL; 701 dprintf("failed to read ctf data\n"); 702 return (NULL); 703 } 704 } 705 706 ctdata.cts_name = ".SUNW_ctf"; 707 ctdata.cts_type = SHT_PROGBITS; 708 ctdata.cts_flags = 0; 709 ctdata.cts_data = fptr->file_ctf_buf; 710 ctdata.cts_size = fptr->file_ctf_size; 711 ctdata.cts_entsize = 1; 712 ctdata.cts_offset = 0; 713 714 symtab.cts_name = fptr->file_ctf_dyn ? ".dynsym" : ".symtab"; 715 symtab.cts_type = symp->sym_hdr.sh_type; 716 symtab.cts_flags = symp->sym_hdr.sh_flags; 717 symtab.cts_data = symp->sym_data->d_buf; 718 symtab.cts_size = symp->sym_hdr.sh_size; 719 symtab.cts_entsize = symp->sym_hdr.sh_entsize; 720 symtab.cts_offset = symp->sym_hdr.sh_offset; 721 722 strtab.cts_name = fptr->file_ctf_dyn ? ".dynstr" : ".strtab"; 723 strtab.cts_type = symp->sym_strhdr.sh_type; 724 strtab.cts_flags = symp->sym_strhdr.sh_flags; 725 strtab.cts_data = symp->sym_strs; 726 strtab.cts_size = symp->sym_strhdr.sh_size; 727 strtab.cts_entsize = symp->sym_strhdr.sh_entsize; 728 strtab.cts_offset = symp->sym_strhdr.sh_offset; 729 730 fptr->file_ctfp = ctf_bufopen(&ctdata, &symtab, &strtab, &err); 731 if (fptr->file_ctfp == NULL) { 732 free(fptr->file_ctf_buf); 733 fptr->file_ctf_buf = NULL; 734 return (NULL); 735 } 736 737 dprintf("loaded %lu bytes of CTF data for %s\n", 738 (ulong_t)fptr->file_ctf_size, fptr->file_pname); 739 740 return (fptr->file_ctfp); 741 } 742 743 ctf_file_t * 744 Paddr_to_ctf(struct ps_prochandle *P, uintptr_t addr) 745 { 746 map_info_t *mptr; 747 file_info_t *fptr; 748 749 if (!P->info_valid) 750 Pupdate_maps(P); 751 752 if ((mptr = Paddr2mptr(P, addr)) == NULL || 753 (fptr = mptr->map_file) == NULL) 754 return (NULL); 755 756 return (Pbuild_file_ctf(P, fptr)); 757 } 758 759 ctf_file_t * 760 Plmid_to_ctf(struct ps_prochandle *P, Lmid_t lmid, const char *name) 761 { 762 map_info_t *mptr; 763 file_info_t *fptr; 764 765 if (name == PR_OBJ_EVERY) 766 return (NULL); 767 768 if ((mptr = object_name_to_map(P, lmid, name)) == NULL || 769 (fptr = mptr->map_file) == NULL) 770 return (NULL); 771 772 return (Pbuild_file_ctf(P, fptr)); 773 } 774 775 ctf_file_t * 776 Pname_to_ctf(struct ps_prochandle *P, const char *name) 777 { 778 return (Plmid_to_ctf(P, PR_LMID_EVERY, name)); 779 } 780 781 /* 782 * If we're not a core file, re-read the /proc/<pid>/auxv file and store 783 * its contents in P->auxv. In the case of a core file, we either 784 * initialized P->auxv in Pcore() from the NT_AUXV, or we don't have an 785 * auxv because the note was missing. 786 */ 787 void 788 Preadauxvec(struct ps_prochandle *P) 789 { 790 char auxfile[64]; 791 struct stat statb; 792 ssize_t naux; 793 int fd; 794 795 if (P->state == PS_DEAD) 796 return; /* Already read during Pgrab_core() */ 797 if (P->state == PS_IDLE) 798 return; /* No aux vec for Pgrab_file() */ 799 800 if (P->auxv != NULL) { 801 free(P->auxv); 802 P->auxv = NULL; 803 P->nauxv = 0; 804 } 805 806 (void) sprintf(auxfile, "/proc/%d/auxv", (int)P->pid); 807 if ((fd = open(auxfile, O_RDONLY)) < 0) 808 return; 809 810 if (fstat(fd, &statb) == 0 && 811 statb.st_size >= sizeof (auxv_t) && 812 (P->auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) { 813 if ((naux = read(fd, P->auxv, statb.st_size)) < 0 || 814 (naux /= sizeof (auxv_t)) < 1) { 815 free(P->auxv); 816 P->auxv = NULL; 817 } else { 818 P->auxv[naux].a_type = AT_NULL; 819 P->auxv[naux].a_un.a_val = 0L; 820 P->nauxv = (int)naux; 821 } 822 } 823 824 (void) close(fd); 825 } 826 827 /* 828 * Return a requested element from the process's aux vector. 829 * Return -1 on failure (this is adequate for our purposes). 830 */ 831 long 832 Pgetauxval(struct ps_prochandle *P, int type) 833 { 834 auxv_t *auxv; 835 836 if (P->auxv == NULL) 837 Preadauxvec(P); 838 839 if (P->auxv == NULL) 840 return (-1); 841 842 for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) { 843 if (auxv->a_type == type) 844 return (auxv->a_un.a_val); 845 } 846 847 return (-1); 848 } 849 850 /* 851 * Return a pointer to our internal copy of the process's aux vector. 852 * The caller should not hold on to this pointer across any libproc calls. 853 */ 854 const auxv_t * 855 Pgetauxvec(struct ps_prochandle *P) 856 { 857 static const auxv_t empty = { AT_NULL, 0L }; 858 859 if (P->auxv == NULL) 860 Preadauxvec(P); 861 862 if (P->auxv == NULL) 863 return (&empty); 864 865 return (P->auxv); 866 } 867 868 /* 869 * Find or build the symbol table for the given mapping. 870 */ 871 static file_info_t * 872 build_map_symtab(struct ps_prochandle *P, map_info_t *mptr) 873 { 874 prmap_t *pmap = &mptr->map_pmap; 875 file_info_t *fptr; 876 rd_loadobj_t *lop; 877 uint_t i; 878 879 if ((fptr = mptr->map_file) != NULL) { 880 Pbuild_file_symtab(P, fptr); 881 return (fptr); 882 } 883 884 if (pmap->pr_mapname[0] == '\0') 885 return (NULL); 886 887 /* 888 * Attempt to find a matching file. 889 * (A file can be mapped at several different addresses.) 890 */ 891 for (i = 0, fptr = list_next(&P->file_head); i < P->num_files; 892 i++, fptr = list_next(fptr)) { 893 if (strcmp(fptr->file_pname, pmap->pr_mapname) == 0 && 894 (lop = fptr->file_lo) != NULL && 895 ((pmap->pr_vaddr <= lop->rl_base && 896 lop->rl_base < pmap->pr_vaddr + pmap->pr_size) || 897 (pmap->pr_vaddr <= lop->rl_data_base && 898 lop->rl_data_base < pmap->pr_vaddr + pmap->pr_size))) { 899 mptr->map_file = fptr; 900 fptr->file_ref++; 901 Pbuild_file_symtab(P, fptr); 902 return (fptr); 903 } 904 } 905 906 /* 907 * If we need to create a new file_info structure, iterate 908 * through the load objects in order to attempt to connect 909 * this new file with its primary text mapping. We again 910 * need to handle ld.so as a special case because we need 911 * to be able to bootstrap librtld_db. 912 */ 913 if ((fptr = file_info_new(P, mptr)) == NULL) 914 return (NULL); 915 916 if (P->map_ldso != mptr) { 917 if (P->rap != NULL) 918 (void) rd_loadobj_iter(P->rap, map_iter, P); 919 else 920 (void) Prd_agent(P); 921 } else { 922 fptr->file_map = mptr; 923 } 924 925 /* 926 * If librtld_db wasn't able to help us connect the file to a primary 927 * text mapping, set file_map to the current mapping because we require 928 * fptr->file_map to be set in Pbuild_file_symtab. librtld_db may be 929 * unaware of what's going on in the rare case that a legitimate ELF 930 * file has been mmap(2)ed into the process address space *without* 931 * the use of dlopen(3x). Why would this happen? See pwdx ... :) 932 */ 933 if (fptr->file_map == NULL) 934 fptr->file_map = mptr; 935 936 Pbuild_file_symtab(P, fptr); 937 938 return (fptr); 939 } 940 941 static int 942 read_ehdr32(struct ps_prochandle *P, Elf32_Ehdr *ehdr, uint_t *phnum, 943 uintptr_t addr) 944 { 945 if (Pread(P, ehdr, sizeof (*ehdr), addr) != sizeof (*ehdr)) 946 return (-1); 947 948 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || 949 ehdr->e_ident[EI_MAG1] != ELFMAG1 || 950 ehdr->e_ident[EI_MAG2] != ELFMAG2 || 951 ehdr->e_ident[EI_MAG3] != ELFMAG3 || 952 ehdr->e_ident[EI_CLASS] != ELFCLASS32 || 953 #ifdef _BIG_ENDIAN 954 ehdr->e_ident[EI_DATA] != ELFDATA2MSB || 955 #else 956 ehdr->e_ident[EI_DATA] != ELFDATA2LSB || 957 #endif 958 ehdr->e_ident[EI_VERSION] != EV_CURRENT) 959 return (-1); 960 961 if ((*phnum = ehdr->e_phnum) == PN_XNUM) { 962 Elf32_Shdr shdr0; 963 964 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) || 965 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) != 966 sizeof (shdr0)) 967 return (-1); 968 969 if (shdr0.sh_info != 0) 970 *phnum = shdr0.sh_info; 971 } 972 973 return (0); 974 } 975 976 static int 977 read_dynamic_phdr32(struct ps_prochandle *P, const Elf32_Ehdr *ehdr, 978 uint_t phnum, Elf32_Phdr *phdr, uintptr_t addr) 979 { 980 uint_t i; 981 982 for (i = 0; i < phnum; i++) { 983 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize; 984 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr)) 985 return (-1); 986 987 if (phdr->p_type == PT_DYNAMIC) 988 return (0); 989 } 990 991 return (-1); 992 } 993 994 #ifdef _LP64 995 static int 996 read_ehdr64(struct ps_prochandle *P, Elf64_Ehdr *ehdr, uint_t *phnum, 997 uintptr_t addr) 998 { 999 if (Pread(P, ehdr, sizeof (Elf64_Ehdr), addr) != sizeof (Elf64_Ehdr)) 1000 return (-1); 1001 1002 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || 1003 ehdr->e_ident[EI_MAG1] != ELFMAG1 || 1004 ehdr->e_ident[EI_MAG2] != ELFMAG2 || 1005 ehdr->e_ident[EI_MAG3] != ELFMAG3 || 1006 ehdr->e_ident[EI_CLASS] != ELFCLASS64 || 1007 #ifdef _BIG_ENDIAN 1008 ehdr->e_ident[EI_DATA] != ELFDATA2MSB || 1009 #else 1010 ehdr->e_ident[EI_DATA] != ELFDATA2LSB || 1011 #endif 1012 ehdr->e_ident[EI_VERSION] != EV_CURRENT) 1013 return (-1); 1014 1015 if ((*phnum = ehdr->e_phnum) == PN_XNUM) { 1016 Elf64_Shdr shdr0; 1017 1018 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) || 1019 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) != 1020 sizeof (shdr0)) 1021 return (-1); 1022 1023 if (shdr0.sh_info != 0) 1024 *phnum = shdr0.sh_info; 1025 } 1026 1027 return (0); 1028 } 1029 1030 static int 1031 read_dynamic_phdr64(struct ps_prochandle *P, const Elf64_Ehdr *ehdr, 1032 uint_t phnum, Elf64_Phdr *phdr, uintptr_t addr) 1033 { 1034 uint_t i; 1035 1036 for (i = 0; i < phnum; i++) { 1037 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize; 1038 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr)) 1039 return (-1); 1040 1041 if (phdr->p_type == PT_DYNAMIC) 1042 return (0); 1043 } 1044 1045 return (-1); 1046 } 1047 #endif /* _LP64 */ 1048 1049 /* 1050 * The text segment for each load object contains the elf header and 1051 * program headers. We can use this information to determine if the 1052 * file that corresponds to the load object is the same file that 1053 * was loaded into the process's address space. There can be a discrepency 1054 * if a file is recompiled after the process is started or if the target 1055 * represents a core file from a differently configured system -- two 1056 * common examples. The DT_CHECKSUM entry in the dynamic section 1057 * provides an easy method of comparison. It is important to note that 1058 * the dynamic section usually lives in the data segment, but the meta 1059 * data we use to find the dynamic section lives in the text segment so 1060 * if either of those segments is absent we can't proceed. 1061 * 1062 * We're looking through the elf file for several items: the symbol tables 1063 * (both dynsym and symtab), the procedure linkage table (PLT) base, 1064 * size, and relocation base, and the CTF information. Most of this can 1065 * be recovered from the loaded image of the file itself, the exceptions 1066 * being the symtab and CTF data. 1067 * 1068 * First we try to open the file that we think corresponds to the load 1069 * object, if the DT_CHECKSUM values match, we're all set, and can simply 1070 * recover all the information we need from the file. If the values of 1071 * DT_CHECKSUM don't match, or if we can't access the file for whatever 1072 * reasaon, we fake up a elf file to use in its stead. If we can't read 1073 * the elf data in the process's address space, we fall back to using 1074 * the file even though it may give inaccurate information. 1075 * 1076 * The elf file that we fake up has to consist of sections for the 1077 * dynsym, the PLT and the dynamic section. Note that in the case of a 1078 * core file, we'll get the CTF data in the file_info_t later on from 1079 * a section embedded the core file (if it's present). 1080 * 1081 * file_differs() conservatively looks for mismatched files, identifying 1082 * a match when there is any ambiguity (since that's the legacy behavior). 1083 */ 1084 static int 1085 file_differs(struct ps_prochandle *P, Elf *elf, file_info_t *fptr) 1086 { 1087 Elf_Scn *scn; 1088 GElf_Shdr shdr; 1089 GElf_Dyn dyn; 1090 Elf_Data *data; 1091 uint_t i, ndyn; 1092 GElf_Xword cksum; 1093 uintptr_t addr; 1094 1095 if (fptr->file_map == NULL) 1096 return (0); 1097 1098 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) != 1099 (CC_CONTENT_TEXT | CC_CONTENT_DATA)) 1100 return (0); 1101 1102 /* 1103 * First, we find the checksum value in the elf file. 1104 */ 1105 scn = NULL; 1106 while ((scn = elf_nextscn(elf, scn)) != NULL) { 1107 if (gelf_getshdr(scn, &shdr) != NULL && 1108 shdr.sh_type == SHT_DYNAMIC) 1109 goto found_shdr; 1110 } 1111 return (0); 1112 1113 found_shdr: 1114 if ((data = elf_getdata(scn, NULL)) == NULL) 1115 return (0); 1116 1117 if (P->status.pr_dmodel == PR_MODEL_ILP32) 1118 ndyn = shdr.sh_size / sizeof (Elf32_Dyn); 1119 #ifdef _LP64 1120 else if (P->status.pr_dmodel == PR_MODEL_LP64) 1121 ndyn = shdr.sh_size / sizeof (Elf64_Dyn); 1122 #endif 1123 else 1124 return (0); 1125 1126 for (i = 0; i < ndyn; i++) { 1127 if (gelf_getdyn(data, i, &dyn) != NULL && 1128 dyn.d_tag == DT_CHECKSUM) 1129 goto found_cksum; 1130 } 1131 return (0); 1132 1133 found_cksum: 1134 cksum = dyn.d_un.d_val; 1135 dprintf("elf cksum value is %llx\n", (u_longlong_t)cksum); 1136 1137 /* 1138 * Get the base of the text mapping that corresponds to this file. 1139 */ 1140 addr = fptr->file_map->map_pmap.pr_vaddr; 1141 1142 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 1143 Elf32_Ehdr ehdr; 1144 Elf32_Phdr phdr; 1145 Elf32_Dyn dync, *dynp; 1146 uint_t phnum, i; 1147 1148 if (read_ehdr32(P, &ehdr, &phnum, addr) != 0 || 1149 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0) 1150 return (0); 1151 1152 if (ehdr.e_type == ET_DYN) 1153 phdr.p_vaddr += addr; 1154 if ((dynp = malloc(phdr.p_filesz)) == NULL) 1155 return (0); 1156 dync.d_tag = DT_NULL; 1157 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) != 1158 phdr.p_filesz) { 1159 free(dynp); 1160 return (0); 1161 } 1162 1163 for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) { 1164 if (dynp[i].d_tag == DT_CHECKSUM) 1165 dync = dynp[i]; 1166 } 1167 1168 free(dynp); 1169 1170 if (dync.d_tag != DT_CHECKSUM) 1171 return (0); 1172 1173 dprintf("image cksum value is %llx\n", 1174 (u_longlong_t)dync.d_un.d_val); 1175 return (dync.d_un.d_val != cksum); 1176 #ifdef _LP64 1177 } else if (P->status.pr_dmodel == PR_MODEL_LP64) { 1178 Elf64_Ehdr ehdr; 1179 Elf64_Phdr phdr; 1180 Elf64_Dyn dync, *dynp; 1181 uint_t phnum, i; 1182 1183 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 || 1184 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0) 1185 return (0); 1186 1187 if (ehdr.e_type == ET_DYN) 1188 phdr.p_vaddr += addr; 1189 if ((dynp = malloc(phdr.p_filesz)) == NULL) 1190 return (0); 1191 dync.d_tag = DT_NULL; 1192 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) != 1193 phdr.p_filesz) { 1194 free(dynp); 1195 return (0); 1196 } 1197 1198 for (i = 0; i < phdr.p_filesz / sizeof (Elf64_Dyn); i++) { 1199 if (dynp[i].d_tag == DT_CHECKSUM) 1200 dync = dynp[i]; 1201 } 1202 1203 free(dynp); 1204 1205 if (dync.d_tag != DT_CHECKSUM) 1206 return (0); 1207 1208 dprintf("image cksum value is %llx\n", 1209 (u_longlong_t)dync.d_un.d_val); 1210 return (dync.d_un.d_val != cksum); 1211 #endif /* _LP64 */ 1212 } 1213 1214 return (0); 1215 } 1216 1217 static Elf * 1218 fake_elf(struct ps_prochandle *P, file_info_t *fptr) 1219 { 1220 enum { 1221 DI_PLTGOT = 0, 1222 DI_JMPREL, 1223 DI_PLTRELSZ, 1224 DI_PLTREL, 1225 DI_SYMTAB, 1226 DI_HASH, 1227 DI_SYMENT, 1228 DI_STRTAB, 1229 DI_STRSZ, 1230 DI_NENT 1231 }; 1232 uintptr_t addr; 1233 size_t size = 0; 1234 caddr_t elfdata = NULL; 1235 Elf *elf; 1236 Elf32_Word nchain; 1237 static char shstr[] = ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt"; 1238 1239 if (fptr->file_map == NULL) 1240 return (NULL); 1241 1242 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) != 1243 (CC_CONTENT_TEXT | CC_CONTENT_DATA)) 1244 return (NULL); 1245 1246 addr = fptr->file_map->map_pmap.pr_vaddr; 1247 1248 /* 1249 * We're building a in memory elf file that will let us use libelf 1250 * for most of the work we need to later (e.g. symbol table lookups). 1251 * We need sections for the dynsym, dynstr, and plt, and we need 1252 * the program headers from the text section. The former is used in 1253 * Pbuild_file_symtab(); the latter is used in several functions in 1254 * Pcore.c to reconstruct the origin of each mapping from the load 1255 * object that spawned it. 1256 * 1257 * Here are some useful pieces of elf trivia that will help 1258 * to elucidate this code. 1259 * 1260 * All the information we need about the dynstr can be found in these 1261 * two entries in the dynamic section: 1262 * 1263 * DT_STRTAB base of dynstr 1264 * DT_STRSZ size of dynstr 1265 * 1266 * So deciphering the dynstr is pretty straightforward. 1267 * 1268 * The dynsym is a little trickier. 1269 * 1270 * DT_SYMTAB base of dynsym 1271 * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym) 1272 * DT_HASH base of hash table for dynamic lookups 1273 * 1274 * The DT_SYMTAB entry gives us any easy way of getting to the base 1275 * of the dynsym, but getting the size involves rooting around in the 1276 * dynamic lookup hash table. Here's the layout of the hash table: 1277 * 1278 * +-------------------+ 1279 * | nbucket | All values are of type 1280 * +-------------------+ Elf32_Word 1281 * | nchain | 1282 * +-------------------+ 1283 * | bucket[0] | 1284 * | . . . | 1285 * | bucket[nbucket-1] | 1286 * +-------------------+ 1287 * | chain[0] | 1288 * | . . . | 1289 * | chain[nchain-1] | 1290 * +-------------------+ 1291 * (figure 5-12 from the SYS V Generic ABI) 1292 * 1293 * Symbols names are hashed into a particular bucket which contains 1294 * an index into the symbol table. Each entry in the symbol table 1295 * has a corresponding entry in the chain table which tells the 1296 * consumer where the next entry in the hash chain is. We can use 1297 * the nchain field to find out the size of the dynsym. 1298 * 1299 * We can figure out the size of the .plt section, but it takes some 1300 * doing. We need to use the following information: 1301 * 1302 * DT_PLTGOT base of the PLT 1303 * DT_JMPREL base of the PLT's relocation section 1304 * DT_PLTRELSZ size of the PLT's relocation section 1305 * DT_PLTREL type of the PLT's relocation section 1306 * 1307 * We can use the relocation section to figure out the address of the 1308 * last entry and subtract off the value of DT_PLTGOT to calculate 1309 * the size of the PLT. 1310 * 1311 * For more information, check out the System V Generic ABI. 1312 */ 1313 1314 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 1315 Elf32_Ehdr ehdr, *ep; 1316 Elf32_Phdr phdr; 1317 Elf32_Shdr *sp; 1318 Elf32_Dyn *dp; 1319 Elf32_Dyn *d[DI_NENT] = { 0 }; 1320 uint_t phnum, i, dcount = 0; 1321 uint32_t off; 1322 size_t pltsz = 0, pltentsz; 1323 1324 if (read_ehdr32(P, &ehdr, &phnum, addr) != 0 || 1325 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0) 1326 return (NULL); 1327 1328 if (ehdr.e_type == ET_DYN) 1329 phdr.p_vaddr += addr; 1330 1331 if ((dp = malloc(phdr.p_filesz)) == NULL) 1332 return (NULL); 1333 1334 if (Pread(P, dp, phdr.p_filesz, phdr.p_vaddr) != 1335 phdr.p_filesz) { 1336 free(dp); 1337 return (NULL); 1338 } 1339 1340 for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) { 1341 switch (dp[i].d_tag) { 1342 /* 1343 * For the .plt section. 1344 */ 1345 case DT_PLTGOT: 1346 d[DI_PLTGOT] = &dp[i]; 1347 continue; 1348 case DT_JMPREL: 1349 d[DI_JMPREL] = &dp[i]; 1350 continue; 1351 case DT_PLTRELSZ: 1352 d[DI_PLTRELSZ] = &dp[i]; 1353 continue; 1354 case DT_PLTREL: 1355 d[DI_PLTREL] = &dp[i]; 1356 continue; 1357 default: 1358 continue; 1359 1360 /* 1361 * For the .dynsym section. 1362 */ 1363 case DT_SYMTAB: 1364 d[DI_SYMTAB] = &dp[i]; 1365 break; 1366 case DT_HASH: 1367 d[DI_HASH] = &dp[i]; 1368 break; 1369 case DT_SYMENT: 1370 d[DI_SYMENT] = &dp[i]; 1371 break; 1372 1373 /* 1374 * For the .dynstr section. 1375 */ 1376 case DT_STRTAB: 1377 d[DI_STRTAB] = &dp[i]; 1378 break; 1379 case DT_STRSZ: 1380 d[DI_STRSZ] = &dp[i]; 1381 break; 1382 } 1383 1384 dcount++; 1385 } 1386 1387 /* 1388 * We need all of those dynamic entries in order to put 1389 * together a complete set of elf sections, but we'll 1390 * let the PLT section slide if need be. The dynsym- and 1391 * dynstr-related dynamic entries are mandatory in both 1392 * executables and shared objects so if one of those is 1393 * missing, we're in some trouble and should abort. 1394 */ 1395 if (dcount + 4 != DI_NENT) { 1396 dprintf("text section missing required dynamic " 1397 "entries\n"); 1398 return (NULL); 1399 } 1400 1401 if (ehdr.e_type == ET_DYN) { 1402 if (d[DI_PLTGOT] != NULL) 1403 d[DI_PLTGOT]->d_un.d_ptr += addr; 1404 if (d[DI_JMPREL] != NULL) 1405 d[DI_JMPREL]->d_un.d_ptr += addr; 1406 d[DI_SYMTAB]->d_un.d_ptr += addr; 1407 d[DI_HASH]->d_un.d_ptr += addr; 1408 d[DI_STRTAB]->d_un.d_ptr += addr; 1409 } 1410 1411 /* elf header */ 1412 size = sizeof (Elf32_Ehdr); 1413 1414 /* program headers from in-core elf fragment */ 1415 size += phnum * ehdr.e_phentsize; 1416 1417 /* unused shdr, and .shstrtab section */ 1418 size += sizeof (Elf32_Shdr); 1419 size += sizeof (Elf32_Shdr); 1420 size += roundup(sizeof (shstr), 4); 1421 1422 /* .dynsym section */ 1423 size += sizeof (Elf32_Shdr); 1424 if (Pread(P, &nchain, sizeof (nchain), 1425 d[DI_HASH]->d_un.d_ptr + 4) != sizeof (nchain)) 1426 goto bad32; 1427 size += sizeof (Elf32_Sym) * nchain; 1428 1429 /* .dynstr section */ 1430 size += sizeof (Elf32_Shdr); 1431 size += roundup(d[DI_STRSZ]->d_un.d_val, 4); 1432 1433 /* .dynamic section */ 1434 size += sizeof (Elf32_Shdr); 1435 size += roundup(phdr.p_filesz, 4); 1436 1437 /* .plt section */ 1438 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL && 1439 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) { 1440 uintptr_t penult, ult; 1441 uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr; 1442 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val; 1443 1444 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) { 1445 uint_t ndx = pltrelsz / sizeof (Elf32_Rela) - 2; 1446 Elf32_Rela r[2]; 1447 1448 if (Pread(P, r, sizeof (r), jmprel + 1449 sizeof (r[0]) * ndx) != sizeof (r)) 1450 goto bad32; 1451 1452 penult = r[0].r_offset; 1453 ult = r[1].r_offset; 1454 1455 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { 1456 uint_t ndx = pltrelsz / sizeof (Elf32_Rel) - 2; 1457 Elf32_Rel r[2]; 1458 1459 if (Pread(P, r, sizeof (r), jmprel + 1460 sizeof (r[0]) * ndx) != sizeof (r)) 1461 goto bad32; 1462 1463 penult = r[0].r_offset; 1464 ult = r[1].r_offset; 1465 } else { 1466 goto bad32; 1467 } 1468 1469 pltentsz = ult - penult; 1470 1471 if (ehdr.e_type == ET_DYN) 1472 ult += addr; 1473 1474 pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz; 1475 1476 size += sizeof (Elf32_Shdr); 1477 size += roundup(pltsz, 4); 1478 } 1479 1480 if ((elfdata = calloc(1, size)) == NULL) 1481 goto bad32; 1482 1483 /* LINTED - alignment */ 1484 ep = (Elf32_Ehdr *)elfdata; 1485 (void) memcpy(ep, &ehdr, offsetof(Elf32_Ehdr, e_phoff)); 1486 1487 ep->e_ehsize = sizeof (Elf32_Ehdr); 1488 ep->e_phoff = sizeof (Elf32_Ehdr); 1489 ep->e_phentsize = ehdr.e_phentsize; 1490 ep->e_phnum = phnum; 1491 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize; 1492 ep->e_shentsize = sizeof (Elf32_Shdr); 1493 ep->e_shnum = (pltsz == 0) ? 5 : 6; 1494 ep->e_shstrndx = 1; 1495 1496 /* LINTED - alignment */ 1497 sp = (Elf32_Shdr *)(elfdata + ep->e_shoff); 1498 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum; 1499 1500 /* 1501 * Copying the program headers directly from the process's 1502 * address space is a little suspect, but since we only 1503 * use them for their address and size values, this is fine. 1504 */ 1505 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize, 1506 addr + ehdr.e_phoff) != phnum * ep->e_phentsize) { 1507 free(elfdata); 1508 goto bad32; 1509 } 1510 1511 /* 1512 * The first elf section is always skipped. 1513 */ 1514 sp++; 1515 1516 /* 1517 * Section Header[1] sh_name: .shstrtab 1518 */ 1519 sp->sh_name = 0; 1520 sp->sh_type = SHT_STRTAB; 1521 sp->sh_flags = SHF_STRINGS; 1522 sp->sh_addr = 0; 1523 sp->sh_offset = off; 1524 sp->sh_size = sizeof (shstr); 1525 sp->sh_link = 0; 1526 sp->sh_info = 0; 1527 sp->sh_addralign = 1; 1528 sp->sh_entsize = 0; 1529 1530 (void) memcpy(&elfdata[off], shstr, sizeof (shstr)); 1531 off += roundup(sp->sh_size, 4); 1532 sp++; 1533 1534 /* 1535 * Section Header[2] sh_name: .dynsym 1536 */ 1537 sp->sh_name = 10; 1538 sp->sh_type = SHT_DYNSYM; 1539 sp->sh_flags = SHF_ALLOC; 1540 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr; 1541 if (ehdr.e_type == ET_DYN) 1542 sp->sh_addr -= addr; 1543 sp->sh_offset = off; 1544 sp->sh_size = nchain * sizeof (Elf32_Sym); 1545 sp->sh_link = 3; 1546 sp->sh_info = 1; 1547 sp->sh_addralign = 4; 1548 sp->sh_entsize = sizeof (Elf32_Sym); 1549 1550 if (Pread(P, &elfdata[off], sp->sh_size, 1551 d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 1552 free(elfdata); 1553 goto bad32; 1554 } 1555 1556 off += roundup(sp->sh_size, 4); 1557 sp++; 1558 1559 /* 1560 * Section Header[3] sh_name: .dynstr 1561 */ 1562 sp->sh_name = 18; 1563 sp->sh_type = SHT_STRTAB; 1564 sp->sh_flags = SHF_ALLOC | SHF_STRINGS; 1565 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr; 1566 if (ehdr.e_type == ET_DYN) 1567 sp->sh_addr -= addr; 1568 sp->sh_offset = off; 1569 sp->sh_size = d[DI_STRSZ]->d_un.d_val; 1570 sp->sh_link = 0; 1571 sp->sh_info = 0; 1572 sp->sh_addralign = 1; 1573 sp->sh_entsize = 0; 1574 1575 if (Pread(P, &elfdata[off], sp->sh_size, 1576 d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) { 1577 free(elfdata); 1578 goto bad32; 1579 } 1580 off += roundup(sp->sh_size, 4); 1581 sp++; 1582 1583 /* 1584 * Section Header[4] sh_name: .dynamic 1585 */ 1586 sp->sh_name = 26; 1587 sp->sh_type = SHT_DYNAMIC; 1588 sp->sh_flags = SHF_WRITE | SHF_ALLOC; 1589 sp->sh_addr = phdr.p_vaddr; 1590 if (ehdr.e_type == ET_DYN) 1591 sp->sh_addr -= addr; 1592 sp->sh_offset = off; 1593 sp->sh_size = phdr.p_filesz; 1594 sp->sh_link = 3; 1595 sp->sh_info = 0; 1596 sp->sh_addralign = 4; 1597 sp->sh_entsize = sizeof (Elf32_Dyn); 1598 1599 (void) memcpy(&elfdata[off], dp, sp->sh_size); 1600 off += roundup(sp->sh_size, 4); 1601 sp++; 1602 1603 /* 1604 * Section Header[5] sh_name: .plt 1605 */ 1606 if (pltsz != 0) { 1607 sp->sh_name = 35; 1608 sp->sh_type = SHT_PROGBITS; 1609 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; 1610 sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr; 1611 if (ehdr.e_type == ET_DYN) 1612 sp->sh_addr -= addr; 1613 sp->sh_offset = off; 1614 sp->sh_size = pltsz; 1615 sp->sh_link = 0; 1616 sp->sh_info = 0; 1617 sp->sh_addralign = 4; 1618 sp->sh_entsize = pltentsz; 1619 1620 if (Pread(P, &elfdata[off], sp->sh_size, 1621 d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) { 1622 free(elfdata); 1623 goto bad32; 1624 } 1625 off += roundup(sp->sh_size, 4); 1626 sp++; 1627 } 1628 1629 free(dp); 1630 goto good; 1631 1632 bad32: 1633 free(dp); 1634 return (NULL); 1635 #ifdef _LP64 1636 } else if (P->status.pr_dmodel == PR_MODEL_LP64) { 1637 Elf64_Ehdr ehdr, *ep; 1638 Elf64_Phdr phdr; 1639 Elf64_Shdr *sp; 1640 Elf64_Dyn *dp; 1641 Elf64_Dyn *d[DI_NENT] = { 0 }; 1642 uint_t phnum, i, dcount = 0; 1643 uint64_t off; 1644 size_t pltsz = 0, pltentsz; 1645 1646 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 || 1647 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0) 1648 return (NULL); 1649 1650 if (ehdr.e_type == ET_DYN) 1651 phdr.p_vaddr += addr; 1652 1653 if ((dp = malloc(phdr.p_filesz)) == NULL) 1654 return (NULL); 1655 1656 if (Pread(P, dp, phdr.p_filesz, phdr.p_vaddr) != 1657 phdr.p_filesz) { 1658 free(dp); 1659 return (NULL); 1660 } 1661 1662 for (i = 0; i < phdr.p_filesz / sizeof (Elf64_Dyn); i++) { 1663 switch (dp[i].d_tag) { 1664 /* 1665 * For the .plt section. 1666 */ 1667 case DT_PLTGOT: 1668 d[DI_PLTGOT] = &dp[i]; 1669 continue; 1670 case DT_JMPREL: 1671 d[DI_JMPREL] = &dp[i]; 1672 continue; 1673 case DT_PLTRELSZ: 1674 d[DI_PLTRELSZ] = &dp[i]; 1675 continue; 1676 case DT_PLTREL: 1677 d[DI_PLTREL] = &dp[i]; 1678 continue; 1679 default: 1680 continue; 1681 1682 /* 1683 * For the .dynsym section. 1684 */ 1685 case DT_SYMTAB: 1686 d[DI_SYMTAB] = &dp[i]; 1687 break; 1688 case DT_HASH: 1689 d[DI_HASH] = &dp[i]; 1690 break; 1691 case DT_SYMENT: 1692 d[DI_SYMENT] = &dp[i]; 1693 break; 1694 1695 /* 1696 * For the .dynstr section. 1697 */ 1698 case DT_STRTAB: 1699 d[DI_STRTAB] = &dp[i]; 1700 break; 1701 case DT_STRSZ: 1702 d[DI_STRSZ] = &dp[i]; 1703 break; 1704 } 1705 1706 dcount++; 1707 } 1708 1709 /* 1710 * We need all of those dynamic entries in order to put 1711 * together a complete set of elf sections, but we'll 1712 * let the PLT section slide if need be. The dynsym- and 1713 * dynstr-related dynamic entries are mandatory in both 1714 * executables and shared objects so if one of those is 1715 * missing, we're in some trouble and should abort. 1716 */ 1717 if (dcount + 4 != DI_NENT) { 1718 dprintf("text section missing required dynamic " 1719 "entries\n"); 1720 return (NULL); 1721 } 1722 1723 if (ehdr.e_type == ET_DYN) { 1724 if (d[DI_PLTGOT] != NULL) 1725 d[DI_PLTGOT]->d_un.d_ptr += addr; 1726 if (d[DI_JMPREL] != NULL) 1727 d[DI_JMPREL]->d_un.d_ptr += addr; 1728 d[DI_SYMTAB]->d_un.d_ptr += addr; 1729 d[DI_HASH]->d_un.d_ptr += addr; 1730 d[DI_STRTAB]->d_un.d_ptr += addr; 1731 } 1732 1733 /* elf header */ 1734 size = sizeof (Elf64_Ehdr); 1735 1736 /* program headers from in-core elf fragment */ 1737 size += phnum * ehdr.e_phentsize; 1738 1739 /* unused shdr, and .shstrtab section */ 1740 size += sizeof (Elf64_Shdr); 1741 size += sizeof (Elf64_Shdr); 1742 size += roundup(sizeof (shstr), 8); 1743 1744 /* .dynsym section */ 1745 size += sizeof (Elf64_Shdr); 1746 if (Pread(P, &nchain, sizeof (nchain), 1747 d[DI_HASH]->d_un.d_ptr + 4) != sizeof (nchain)) 1748 goto bad64; 1749 size += sizeof (Elf64_Sym) * nchain; 1750 1751 /* .dynstr section */ 1752 size += sizeof (Elf64_Shdr); 1753 size += roundup(d[DI_STRSZ]->d_un.d_val, 8); 1754 1755 /* .dynamic section */ 1756 size += sizeof (Elf64_Shdr); 1757 size += roundup(phdr.p_filesz, 8); 1758 1759 /* .plt section */ 1760 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL && 1761 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) { 1762 uintptr_t penult, ult; 1763 uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr; 1764 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val; 1765 1766 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) { 1767 uint_t ndx = pltrelsz / sizeof (Elf64_Rela) - 2; 1768 Elf64_Rela r[2]; 1769 1770 if (Pread(P, r, sizeof (r), jmprel + 1771 sizeof (r[0]) * ndx) != sizeof (r)) 1772 goto bad64; 1773 1774 penult = r[0].r_offset; 1775 ult = r[1].r_offset; 1776 1777 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { 1778 uint_t ndx = pltrelsz / sizeof (Elf64_Rel) - 2; 1779 Elf64_Rel r[2]; 1780 1781 if (Pread(P, r, sizeof (r), jmprel + 1782 sizeof (r[0]) * ndx) != sizeof (r)) 1783 goto bad64; 1784 1785 penult = r[0].r_offset; 1786 ult = r[1].r_offset; 1787 } else { 1788 goto bad64; 1789 } 1790 1791 pltentsz = ult - penult; 1792 1793 if (ehdr.e_type == ET_DYN) 1794 ult += addr; 1795 1796 pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz; 1797 1798 size += sizeof (Elf64_Shdr); 1799 size += roundup(pltsz, 8); 1800 } 1801 1802 if ((elfdata = calloc(1, size)) == NULL) 1803 goto bad64; 1804 1805 /* LINTED - alignment */ 1806 ep = (Elf64_Ehdr *)elfdata; 1807 (void) memcpy(ep, &ehdr, offsetof(Elf64_Ehdr, e_phoff)); 1808 1809 ep->e_ehsize = sizeof (Elf64_Ehdr); 1810 ep->e_phoff = sizeof (Elf64_Ehdr); 1811 ep->e_phentsize = ehdr.e_phentsize; 1812 ep->e_phnum = phnum; 1813 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize; 1814 ep->e_shentsize = sizeof (Elf64_Shdr); 1815 ep->e_shnum = (pltsz == 0) ? 5 : 6; 1816 ep->e_shstrndx = 1; 1817 1818 /* LINTED - alignment */ 1819 sp = (Elf64_Shdr *)(elfdata + ep->e_shoff); 1820 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum; 1821 1822 /* 1823 * Copying the program headers directly from the process's 1824 * address space is a little suspect, but since we only 1825 * use them for their address and size values, this is fine. 1826 */ 1827 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize, 1828 addr + ehdr.e_phoff) != phnum * ep->e_phentsize) { 1829 free(elfdata); 1830 goto bad64; 1831 } 1832 1833 /* 1834 * The first elf section is always skipped. 1835 */ 1836 sp++; 1837 1838 /* 1839 * Section Header[1] sh_name: .shstrtab 1840 */ 1841 sp->sh_name = 0; 1842 sp->sh_type = SHT_STRTAB; 1843 sp->sh_flags = SHF_STRINGS; 1844 sp->sh_addr = 0; 1845 sp->sh_offset = off; 1846 sp->sh_size = sizeof (shstr); 1847 sp->sh_link = 0; 1848 sp->sh_info = 0; 1849 sp->sh_addralign = 1; 1850 sp->sh_entsize = 0; 1851 1852 (void) memcpy(&elfdata[off], shstr, sizeof (shstr)); 1853 off += roundup(sp->sh_size, 8); 1854 sp++; 1855 1856 /* 1857 * Section Header[2] sh_name: .dynsym 1858 */ 1859 sp->sh_name = 10; 1860 sp->sh_type = SHT_DYNSYM; 1861 sp->sh_flags = SHF_ALLOC; 1862 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr; 1863 if (ehdr.e_type == ET_DYN) 1864 sp->sh_addr -= addr; 1865 sp->sh_offset = off; 1866 sp->sh_size = nchain * sizeof (Elf64_Sym); 1867 sp->sh_link = 3; 1868 sp->sh_info = 1; 1869 sp->sh_addralign = 8; 1870 sp->sh_entsize = sizeof (Elf64_Sym); 1871 1872 if (Pread(P, &elfdata[off], sp->sh_size, 1873 d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 1874 free(elfdata); 1875 goto bad64; 1876 } 1877 1878 off += roundup(sp->sh_size, 8); 1879 sp++; 1880 1881 /* 1882 * Section Header[3] sh_name: .dynstr 1883 */ 1884 sp->sh_name = 18; 1885 sp->sh_type = SHT_STRTAB; 1886 sp->sh_flags = SHF_ALLOC | SHF_STRINGS; 1887 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr; 1888 if (ehdr.e_type == ET_DYN) 1889 sp->sh_addr -= addr; 1890 sp->sh_offset = off; 1891 sp->sh_size = d[DI_STRSZ]->d_un.d_val; 1892 sp->sh_link = 0; 1893 sp->sh_info = 0; 1894 sp->sh_addralign = 1; 1895 sp->sh_entsize = 0; 1896 1897 if (Pread(P, &elfdata[off], sp->sh_size, 1898 d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) { 1899 free(elfdata); 1900 goto bad64; 1901 } 1902 off += roundup(sp->sh_size, 8); 1903 sp++; 1904 1905 /* 1906 * Section Header[4] sh_name: .dynamic 1907 */ 1908 sp->sh_name = 26; 1909 sp->sh_type = SHT_DYNAMIC; 1910 sp->sh_flags = SHF_WRITE | SHF_ALLOC; 1911 sp->sh_addr = phdr.p_vaddr; 1912 if (ehdr.e_type == ET_DYN) 1913 sp->sh_addr -= addr; 1914 sp->sh_offset = off; 1915 sp->sh_size = phdr.p_filesz; 1916 sp->sh_link = 3; 1917 sp->sh_info = 0; 1918 sp->sh_addralign = 8; 1919 sp->sh_entsize = sizeof (Elf64_Dyn); 1920 1921 (void) memcpy(&elfdata[off], dp, sp->sh_size); 1922 off += roundup(sp->sh_size, 8); 1923 sp++; 1924 1925 /* 1926 * Section Header[5] sh_name: .plt 1927 */ 1928 if (pltsz != 0) { 1929 sp->sh_name = 35; 1930 sp->sh_type = SHT_PROGBITS; 1931 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; 1932 sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr; 1933 if (ehdr.e_type == ET_DYN) 1934 sp->sh_addr -= addr; 1935 sp->sh_offset = off; 1936 sp->sh_size = pltsz; 1937 sp->sh_link = 0; 1938 sp->sh_info = 0; 1939 sp->sh_addralign = 8; 1940 sp->sh_entsize = pltentsz; 1941 1942 if (Pread(P, &elfdata[off], sp->sh_size, 1943 d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) { 1944 free(elfdata); 1945 goto bad64; 1946 } 1947 off += roundup(sp->sh_size, 8); 1948 sp++; 1949 } 1950 1951 free(dp); 1952 goto good; 1953 1954 bad64: 1955 free(dp); 1956 return (NULL); 1957 #endif /* _LP64 */ 1958 } 1959 good: 1960 if ((elf = elf_memory(elfdata, size)) == NULL) { 1961 free(elfdata); 1962 return (NULL); 1963 } 1964 1965 fptr->file_elfmem = elfdata; 1966 1967 return (elf); 1968 } 1969 1970 /* 1971 * We wouldn't need these if qsort(3C) took an argument for the callback... 1972 */ 1973 static mutex_t sort_mtx = DEFAULTMUTEX; 1974 static char *sort_strs; 1975 static GElf_Sym *sort_syms; 1976 1977 int 1978 byaddr_cmp_common(GElf_Sym *a, char *aname, GElf_Sym *b, char *bname) 1979 { 1980 if (a->st_value < b->st_value) 1981 return (-1); 1982 if (a->st_value > b->st_value) 1983 return (1); 1984 1985 /* 1986 * Prefer the function to the non-function. 1987 */ 1988 if (GELF_ST_TYPE(a->st_info) != GELF_ST_TYPE(b->st_info)) { 1989 if (GELF_ST_TYPE(a->st_info) == STT_FUNC) 1990 return (-1); 1991 if (GELF_ST_TYPE(b->st_info) == STT_FUNC) 1992 return (1); 1993 } 1994 1995 /* 1996 * Prefer the weak or strong global symbol to the local symbol. 1997 */ 1998 if (GELF_ST_BIND(a->st_info) != GELF_ST_BIND(b->st_info)) { 1999 if (GELF_ST_BIND(b->st_info) == STB_LOCAL) 2000 return (-1); 2001 if (GELF_ST_BIND(a->st_info) == STB_LOCAL) 2002 return (1); 2003 } 2004 2005 /* 2006 * Prefer the symbol that doesn't begin with a '$' since compilers and 2007 * other symbol generators often use it as a prefix. 2008 */ 2009 if (*bname == '$') 2010 return (-1); 2011 if (*aname == '$') 2012 return (1); 2013 2014 /* 2015 * Prefer the name with fewer leading underscores in the name. 2016 */ 2017 while (*aname == '_' && *bname == '_') { 2018 aname++; 2019 bname++; 2020 } 2021 2022 if (*bname == '_') 2023 return (-1); 2024 if (*aname == '_') 2025 return (1); 2026 2027 /* 2028 * Prefer the symbol with the smaller size. 2029 */ 2030 if (a->st_size < b->st_size) 2031 return (-1); 2032 if (a->st_size > b->st_size) 2033 return (1); 2034 2035 /* 2036 * All other factors being equal, fall back to lexicographic order. 2037 */ 2038 return (strcmp(aname, bname)); 2039 } 2040 2041 static int 2042 byaddr_cmp(const void *aa, const void *bb) 2043 { 2044 GElf_Sym *a = &sort_syms[*(uint_t *)aa]; 2045 GElf_Sym *b = &sort_syms[*(uint_t *)bb]; 2046 char *aname = sort_strs + a->st_name; 2047 char *bname = sort_strs + b->st_name; 2048 2049 return (byaddr_cmp_common(a, aname, b, bname)); 2050 } 2051 2052 static int 2053 byname_cmp(const void *aa, const void *bb) 2054 { 2055 GElf_Sym *a = &sort_syms[*(uint_t *)aa]; 2056 GElf_Sym *b = &sort_syms[*(uint_t *)bb]; 2057 char *aname = sort_strs + a->st_name; 2058 char *bname = sort_strs + b->st_name; 2059 2060 return (strcmp(aname, bname)); 2061 } 2062 2063 void 2064 optimize_symtab(sym_tbl_t *symtab) 2065 { 2066 GElf_Sym *symp, *syms; 2067 uint_t i, *indexa, *indexb; 2068 Elf_Data *data; 2069 size_t symn, strsz, count; 2070 2071 if (symtab == NULL || symtab->sym_data == NULL || 2072 symtab->sym_byaddr != NULL) 2073 return; 2074 2075 data = symtab->sym_data; 2076 symn = symtab->sym_symn; 2077 strsz = symtab->sym_strsz; 2078 2079 symp = syms = malloc(sizeof (GElf_Sym) * symn); 2080 2081 /* 2082 * First record all the symbols into a table and count up the ones 2083 * that we're interested in. We mark symbols as invalid by setting 2084 * the st_name to an illegal value. 2085 */ 2086 for (i = 0, count = 0; i < symn; i++, symp++) { 2087 if (gelf_getsym(data, i, symp) != NULL && 2088 symp->st_name < strsz && 2089 IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info))) 2090 count++; 2091 else 2092 symp->st_name = strsz; 2093 } 2094 2095 /* 2096 * Allocate sufficient space for both tables and populate them 2097 * with the same symbols we just counted. 2098 */ 2099 symtab->sym_count = count; 2100 indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count); 2101 indexb = symtab->sym_byname = calloc(sizeof (uint_t), count); 2102 2103 for (i = 0, symp = syms; i < symn; i++, symp++) { 2104 if (symp->st_name < strsz) 2105 *indexa++ = *indexb++ = i; 2106 } 2107 2108 /* 2109 * Sort the two tables according to the appropriate criteria. 2110 */ 2111 (void) mutex_lock(&sort_mtx); 2112 sort_strs = symtab->sym_strs; 2113 sort_syms = syms; 2114 2115 qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp); 2116 qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp); 2117 2118 sort_strs = NULL; 2119 sort_syms = NULL; 2120 (void) mutex_unlock(&sort_mtx); 2121 2122 free(syms); 2123 } 2124 2125 /* 2126 * Build the symbol table for the given mapped file. 2127 */ 2128 void 2129 Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) 2130 { 2131 char objectfile[PATH_MAX]; 2132 uint_t i; 2133 2134 GElf_Ehdr ehdr; 2135 GElf_Sym s; 2136 2137 Elf_Data *shdata; 2138 Elf_Scn *scn; 2139 Elf *elf; 2140 size_t nshdrs, shstrndx; 2141 2142 struct { 2143 GElf_Shdr c_shdr; 2144 Elf_Data *c_data; 2145 const char *c_name; 2146 } *cp, *cache = NULL, *dyn = NULL, *plt = NULL, *ctf = NULL; 2147 2148 if (fptr->file_init) 2149 return; /* We've already processed this file */ 2150 2151 /* 2152 * Mark the file_info struct as having the symbol table initialized 2153 * even if we fail below. We tried once; we don't try again. 2154 */ 2155 fptr->file_init = 1; 2156 2157 if (elf_version(EV_CURRENT) == EV_NONE) { 2158 dprintf("libproc ELF version is more recent than libelf\n"); 2159 return; 2160 } 2161 2162 if (P->state == PS_DEAD || P->state == PS_IDLE) { 2163 /* 2164 * If we're a not live, we can't open files from the /proc 2165 * object directory; we have only the mapping and file names 2166 * to guide us. We prefer the file_lname, but need to handle 2167 * the case of it being NULL in order to bootstrap: we first 2168 * come here during rd_new() when the only information we have 2169 * is interpreter name associated with the AT_BASE mapping. 2170 */ 2171 (void) snprintf(objectfile, sizeof (objectfile), "%s", 2172 fptr->file_lname ? fptr->file_lname : fptr->file_pname); 2173 } else { 2174 (void) snprintf(objectfile, sizeof (objectfile), 2175 "/proc/%d/object/%s", (int)P->pid, fptr->file_pname); 2176 } 2177 2178 /* 2179 * Open the object file, create the elf file, and then get the elf 2180 * header and .shstrtab data buffer so we can process sections by 2181 * name. If anything goes wrong try to fake up an elf file from 2182 * the in-core elf image. 2183 */ 2184 if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) { 2185 dprintf("Pbuild_file_symtab: failed to open %s: %s\n", 2186 objectfile, strerror(errno)); 2187 2188 if ((elf = fake_elf(P, fptr)) == NULL || 2189 elf_kind(elf) != ELF_K_ELF || 2190 gelf_getehdr(elf, &ehdr) == NULL || 2191 elf_getshnum(elf, &nshdrs) == 0 || 2192 elf_getshstrndx(elf, &shstrndx) == 0 || 2193 (scn = elf_getscn(elf, shstrndx)) == NULL || 2194 (shdata = elf_getdata(scn, NULL)) == NULL) { 2195 dprintf("failed to fake up ELF file\n"); 2196 return; 2197 } 2198 2199 } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL || 2200 elf_kind(elf) != ELF_K_ELF || 2201 gelf_getehdr(elf, &ehdr) == NULL || 2202 elf_getshnum(elf, &nshdrs) == 0 || 2203 elf_getshstrndx(elf, &shstrndx) == 0 || 2204 (scn = elf_getscn(elf, shstrndx)) == NULL || 2205 (shdata = elf_getdata(scn, NULL)) == NULL) { 2206 dprintf("failed to process ELF file %s: %s\n", 2207 objectfile, elf_errmsg(elf_errno())); 2208 2209 if ((elf = fake_elf(P, fptr)) == NULL || 2210 elf_kind(elf) != ELF_K_ELF || 2211 gelf_getehdr(elf, &ehdr) == NULL || 2212 elf_getshnum(elf, &nshdrs) == 0 || 2213 elf_getshstrndx(elf, &shstrndx) == 0 || 2214 (scn = elf_getscn(elf, shstrndx)) == NULL || 2215 (shdata = elf_getdata(scn, NULL)) == NULL) { 2216 dprintf("failed to fake up ELF file\n"); 2217 goto bad; 2218 } 2219 2220 } else if (file_differs(P, elf, fptr)) { 2221 Elf *newelf; 2222 2223 /* 2224 * Before we get too excited about this elf file, we'll check 2225 * its checksum value against the value we have in memory. If 2226 * they don't agree, we try to fake up a new elf file and 2227 * proceed with that instead. 2228 */ 2229 2230 dprintf("ELF file %s (%lx) doesn't match in-core image\n", 2231 fptr->file_pname, 2232 (ulong_t)fptr->file_map->map_pmap.pr_vaddr); 2233 2234 if ((newelf = fake_elf(P, fptr)) == NULL || 2235 elf_kind(newelf) != ELF_K_ELF || 2236 gelf_getehdr(newelf, &ehdr) == NULL || 2237 elf_getshnum(newelf, &nshdrs) == 0 || 2238 elf_getshstrndx(newelf, &shstrndx) == 0 || 2239 (scn = elf_getscn(newelf, shstrndx)) == NULL || 2240 (shdata = elf_getdata(scn, NULL)) == NULL) { 2241 dprintf("failed to fake up ELF file\n"); 2242 } else { 2243 (void) elf_end(elf); 2244 elf = newelf; 2245 2246 dprintf("switched to faked up ELF file\n"); 2247 } 2248 } 2249 2250 if ((cache = malloc(nshdrs * sizeof (*cache))) == NULL) { 2251 dprintf("failed to malloc section cache for %s\n", objectfile); 2252 goto bad; 2253 } 2254 2255 dprintf("processing ELF file %s\n", objectfile); 2256 fptr->file_class = ehdr.e_ident[EI_CLASS]; 2257 fptr->file_etype = ehdr.e_type; 2258 fptr->file_elf = elf; 2259 fptr->file_shstrs = shdata->d_buf; 2260 fptr->file_shstrsz = shdata->d_size; 2261 2262 /* 2263 * Iterate through each section, caching its section header, data 2264 * pointer, and name. We use this for handling sh_link values below. 2265 */ 2266 for (cp = cache + 1, scn = NULL; scn = elf_nextscn(elf, scn); cp++) { 2267 if (gelf_getshdr(scn, &cp->c_shdr) == NULL) 2268 goto bad; /* Failed to get section header */ 2269 2270 if ((cp->c_data = elf_getdata(scn, NULL)) == NULL) 2271 goto bad; /* Failed to get section data */ 2272 2273 if (cp->c_shdr.sh_name >= shdata->d_size) 2274 goto bad; /* Corrupt section name */ 2275 2276 cp->c_name = (const char *)shdata->d_buf + cp->c_shdr.sh_name; 2277 } 2278 2279 /* 2280 * Now iterate through the section cache in order to locate info 2281 * for the .symtab, .dynsym, .dynamic, .plt, and .SUNW_ctf sections: 2282 */ 2283 for (i = 1, cp = cache + 1; i < nshdrs; i++, cp++) { 2284 GElf_Shdr *shp = &cp->c_shdr; 2285 2286 if (shp->sh_type == SHT_SYMTAB || shp->sh_type == SHT_DYNSYM) { 2287 sym_tbl_t *symp = shp->sh_type == SHT_SYMTAB ? 2288 &fptr->file_symtab : &fptr->file_dynsym; 2289 2290 /* 2291 * It's possible that the we already got the symbol 2292 * table from the core file itself. Either the file 2293 * differs in which case our faked up elf file will 2294 * only contain the dynsym (not the symtab) or the 2295 * file matches in which case we'll just be replacing 2296 * the symbol table we pulled out of the core file 2297 * with an equivalent one. In either case, this 2298 * check isn't essential, but it's a good idea. 2299 */ 2300 if (symp->sym_data == NULL) { 2301 symp->sym_data = cp->c_data; 2302 symp->sym_symn = shp->sh_size / shp->sh_entsize; 2303 symp->sym_strs = 2304 cache[shp->sh_link].c_data->d_buf; 2305 symp->sym_strsz = 2306 cache[shp->sh_link].c_data->d_size; 2307 symp->sym_hdr = cp->c_shdr; 2308 symp->sym_strhdr = cache[shp->sh_link].c_shdr; 2309 } 2310 2311 } else if (shp->sh_type == SHT_DYNAMIC) { 2312 dyn = cp; 2313 2314 } else if (strcmp(cp->c_name, ".plt") == 0) { 2315 plt = cp; 2316 2317 } else if (strcmp(cp->c_name, ".SUNW_ctf") == 0) { 2318 /* 2319 * Skip over bogus CTF sections so they don't come back 2320 * to haunt us later. 2321 */ 2322 if (shp->sh_link == 0 || 2323 shp->sh_link >= nshdrs || 2324 (cache[shp->sh_link].c_shdr.sh_type != SHT_DYNSYM && 2325 cache[shp->sh_link].c_shdr.sh_type != SHT_SYMTAB)) { 2326 dprintf("Bad sh_link %d for " 2327 "CTF\n", shp->sh_link); 2328 continue; 2329 } 2330 ctf = cp; 2331 } 2332 } 2333 2334 /* 2335 * At this point, we've found all the symbol tables we're ever going 2336 * to find: the ones in the loop above and possibly the symtab that 2337 * was included in the core file. Before we perform any lookups, we 2338 * create sorted versions to optimize for lookups. 2339 */ 2340 optimize_symtab(&fptr->file_symtab); 2341 optimize_symtab(&fptr->file_dynsym); 2342 2343 /* 2344 * Fill in the base address of the text mapping for shared libraries. 2345 * This allows us to translate symbols before librtld_db is ready. 2346 */ 2347 if (fptr->file_etype == ET_DYN) { 2348 fptr->file_dyn_base = fptr->file_map->map_pmap.pr_vaddr - 2349 fptr->file_map->map_pmap.pr_offset; 2350 dprintf("setting file_dyn_base for %s to %p\n", 2351 objectfile, (void *)fptr->file_dyn_base); 2352 } 2353 2354 /* 2355 * Record the CTF section information in the file info structure. 2356 */ 2357 if (ctf != NULL) { 2358 fptr->file_ctf_off = ctf->c_shdr.sh_offset; 2359 fptr->file_ctf_size = ctf->c_shdr.sh_size; 2360 if (ctf->c_shdr.sh_link != 0 && 2361 cache[ctf->c_shdr.sh_link].c_shdr.sh_type == SHT_DYNSYM) 2362 fptr->file_ctf_dyn = 1; 2363 } 2364 2365 if (fptr->file_lo == NULL) 2366 goto done; /* Nothing else to do if no load object info */ 2367 2368 /* 2369 * If the object is a shared library and we have a different rl_base 2370 * value, reset file_dyn_base according to librtld_db's information. 2371 */ 2372 if (fptr->file_etype == ET_DYN && 2373 fptr->file_lo->rl_base != fptr->file_dyn_base) { 2374 dprintf("resetting file_dyn_base for %s to %p\n", 2375 objectfile, (void *)fptr->file_lo->rl_base); 2376 fptr->file_dyn_base = fptr->file_lo->rl_base; 2377 } 2378 2379 /* 2380 * Fill in the PLT information for this file if a PLT symbol is found. 2381 */ 2382 if (sym_by_name(&fptr->file_dynsym, "_PROCEDURE_LINKAGE_TABLE_", &s, 2383 NULL) != NULL) { 2384 fptr->file_plt_base = s.st_value + fptr->file_dyn_base; 2385 fptr->file_plt_size = (plt != NULL) ? plt->c_shdr.sh_size : 0; 2386 2387 /* 2388 * Bring the load object up to date; it is the only way the 2389 * user has to access the PLT data. The PLT information in the 2390 * rd_loadobj_t is not set in the call to map_iter() (the 2391 * callback for rd_loadobj_iter) where we set file_lo. 2392 */ 2393 fptr->file_lo->rl_plt_base = fptr->file_plt_base; 2394 fptr->file_lo->rl_plt_size = fptr->file_plt_size; 2395 2396 dprintf("PLT found at %p, size = %lu\n", 2397 (void *)fptr->file_plt_base, (ulong_t)fptr->file_plt_size); 2398 } 2399 2400 /* 2401 * Fill in the PLT information. 2402 */ 2403 if (dyn != NULL) { 2404 uintptr_t dynaddr = dyn->c_shdr.sh_addr + fptr->file_dyn_base; 2405 size_t ndyn = dyn->c_shdr.sh_size / dyn->c_shdr.sh_entsize; 2406 GElf_Dyn d; 2407 2408 for (i = 0; i < ndyn; i++) { 2409 if (gelf_getdyn(dyn->c_data, i, &d) != NULL && 2410 d.d_tag == DT_JMPREL) { 2411 fptr->file_jmp_rel = 2412 d.d_un.d_ptr + fptr->file_dyn_base; 2413 break; 2414 } 2415 } 2416 2417 dprintf("_DYNAMIC found at %p, %lu entries, DT_JMPREL = %p\n", 2418 (void *)dynaddr, (ulong_t)ndyn, (void *)fptr->file_jmp_rel); 2419 } 2420 2421 done: 2422 free(cache); 2423 return; 2424 2425 bad: 2426 if (cache != NULL) 2427 free(cache); 2428 2429 (void) elf_end(elf); 2430 fptr->file_elf = NULL; 2431 if (fptr->file_elfmem != NULL) { 2432 free(fptr->file_elfmem); 2433 fptr->file_elfmem = NULL; 2434 } 2435 (void) close(fptr->file_fd); 2436 fptr->file_fd = -1; 2437 } 2438 2439 /* 2440 * Given a process virtual address, return the map_info_t containing it. 2441 * If none found, return NULL. 2442 */ 2443 map_info_t * 2444 Paddr2mptr(struct ps_prochandle *P, uintptr_t addr) 2445 { 2446 int lo = 0; 2447 int hi = P->map_count - 1; 2448 int mid; 2449 map_info_t *mp; 2450 2451 while (lo <= hi) { 2452 2453 mid = (lo + hi) / 2; 2454 mp = &P->mappings[mid]; 2455 2456 /* check that addr is in [vaddr, vaddr + size) */ 2457 if ((addr - mp->map_pmap.pr_vaddr) < mp->map_pmap.pr_size) 2458 return (mp); 2459 2460 if (addr < mp->map_pmap.pr_vaddr) 2461 hi = mid - 1; 2462 else 2463 lo = mid + 1; 2464 } 2465 2466 return (NULL); 2467 } 2468 2469 /* 2470 * Return the map_info_t for the executable file. 2471 * If not found, return NULL. 2472 */ 2473 static map_info_t * 2474 exec_map(struct ps_prochandle *P) 2475 { 2476 uint_t i; 2477 map_info_t *mptr; 2478 map_info_t *mold = NULL; 2479 file_info_t *fptr; 2480 uintptr_t base; 2481 2482 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) { 2483 if (mptr->map_pmap.pr_mapname[0] == '\0') 2484 continue; 2485 if (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) { 2486 if ((fptr = mptr->map_file) != NULL && 2487 fptr->file_lo != NULL) { 2488 base = fptr->file_lo->rl_base; 2489 if (base >= mptr->map_pmap.pr_vaddr && 2490 base < mptr->map_pmap.pr_vaddr + 2491 mptr->map_pmap.pr_size) /* text space */ 2492 return (mptr); 2493 mold = mptr; /* must be the data */ 2494 continue; 2495 } 2496 /* This is a poor way to test for text space */ 2497 if (!(mptr->map_pmap.pr_mflags & MA_EXEC) || 2498 (mptr->map_pmap.pr_mflags & MA_WRITE)) { 2499 mold = mptr; 2500 continue; 2501 } 2502 return (mptr); 2503 } 2504 } 2505 2506 return (mold); 2507 } 2508 2509 /* 2510 * Given a shared object name, return the map_info_t for it. If no matching 2511 * object is found, return NULL. Normally, the link maps contain the full 2512 * object pathname, e.g. /usr/lib/libc.so.1. We allow the object name to 2513 * take one of the following forms: 2514 * 2515 * 1. An exact match (i.e. a full pathname): "/usr/lib/libc.so.1" 2516 * 2. An exact basename match: "libc.so.1" 2517 * 3. An initial basename match up to a '.' suffix: "libc.so" or "libc" 2518 * 4. The literal string "a.out" is an alias for the executable mapping 2519 * 2520 * The third case is a convenience for callers and may not be necessary. 2521 * 2522 * As the exact same object name may be loaded on different link maps (see 2523 * dlmopen(3DL)), we also allow the caller to resolve the object name by 2524 * specifying a particular link map id. If lmid is PR_LMID_EVERY, the 2525 * first matching name will be returned, regardless of the link map id. 2526 */ 2527 static map_info_t * 2528 object_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *objname) 2529 { 2530 map_info_t *mp; 2531 file_info_t *fp; 2532 size_t objlen; 2533 uint_t i; 2534 2535 /* 2536 * First pass: look for exact matches of the entire pathname or 2537 * basename (cases 1 and 2 above): 2538 */ 2539 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) { 2540 2541 if (mp->map_pmap.pr_mapname[0] == '\0' || 2542 (fp = mp->map_file) == NULL || fp->file_lname == NULL) 2543 continue; 2544 2545 if (lmid != PR_LMID_EVERY && 2546 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident)) 2547 continue; 2548 2549 /* 2550 * If we match, return the primary text mapping; otherwise 2551 * just return the mapping we matched. 2552 */ 2553 if (strcmp(fp->file_lname, objname) == 0 || 2554 strcmp(fp->file_lbase, objname) == 0) 2555 return (fp->file_map ? fp->file_map : mp); 2556 } 2557 2558 objlen = strlen(objname); 2559 2560 /* 2561 * Second pass: look for partial matches (case 3 above): 2562 */ 2563 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) { 2564 2565 if (mp->map_pmap.pr_mapname[0] == '\0' || 2566 (fp = mp->map_file) == NULL || fp->file_lname == NULL) 2567 continue; 2568 2569 if (lmid != PR_LMID_EVERY && 2570 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident)) 2571 continue; 2572 2573 /* 2574 * If we match, return the primary text mapping; otherwise 2575 * just return the mapping we matched. 2576 */ 2577 if (strncmp(fp->file_lbase, objname, objlen) == 0 && 2578 fp->file_lbase[objlen] == '.') 2579 return (fp->file_map ? fp->file_map : mp); 2580 } 2581 2582 /* 2583 * One last check: we allow "a.out" to always alias the executable, 2584 * assuming this name was not in use for something else. 2585 */ 2586 if ((lmid == PR_LMID_EVERY || lmid == LM_ID_BASE) && 2587 (strcmp(objname, "a.out") == 0)) 2588 return (P->map_exec); 2589 2590 return (NULL); 2591 } 2592 2593 static map_info_t * 2594 object_name_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name) 2595 { 2596 map_info_t *mptr; 2597 2598 if (!P->info_valid) 2599 Pupdate_maps(P); 2600 2601 if (P->map_exec == NULL && ((mptr = Paddr2mptr(P, 2602 Pgetauxval(P, AT_ENTRY))) != NULL || (mptr = exec_map(P)) != NULL)) 2603 P->map_exec = mptr; 2604 2605 if (P->map_ldso == NULL && (mptr = Paddr2mptr(P, 2606 Pgetauxval(P, AT_BASE))) != NULL) 2607 P->map_ldso = mptr; 2608 2609 if (name == PR_OBJ_EXEC) 2610 mptr = P->map_exec; 2611 else if (name == PR_OBJ_LDSO) 2612 mptr = P->map_ldso; 2613 else if (Prd_agent(P) != NULL || P->state == PS_IDLE) 2614 mptr = object_to_map(P, lmid, name); 2615 else 2616 mptr = NULL; 2617 2618 return (mptr); 2619 } 2620 2621 /* 2622 * When two symbols are found by address, decide which one is to be preferred. 2623 */ 2624 static GElf_Sym * 2625 sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2) 2626 { 2627 /* 2628 * Prefer the non-NULL symbol. 2629 */ 2630 if (sym1 == NULL) 2631 return (sym2); 2632 if (sym2 == NULL) 2633 return (sym1); 2634 2635 /* 2636 * Defer to the sort ordering... 2637 */ 2638 return (byaddr_cmp_common(sym1, name1, sym2, name2) <= 0 ? sym1 : sym2); 2639 } 2640 2641 /* 2642 * Look up a symbol by address in the specified symbol table. 2643 * Adjustment to 'addr' must already have been made for the 2644 * offset of the symbol if this is a dynamic library symbol table. 2645 */ 2646 static GElf_Sym * 2647 sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp) 2648 { 2649 Elf_Data *data = symtab->sym_data; 2650 GElf_Sym sym, osym; 2651 uint_t i, oid, *byaddr = symtab->sym_byaddr; 2652 int min, max, mid, omid, found = 0; 2653 2654 if (data == NULL) 2655 return (NULL); 2656 2657 min = 0; 2658 max = symtab->sym_count - 1; 2659 osym.st_value = 0; 2660 2661 /* 2662 * We can't return when we've found a match, we have to continue 2663 * searching for the closest matching symbol. 2664 */ 2665 while (min <= max) { 2666 mid = (max + min) / 2; 2667 2668 i = byaddr[mid]; 2669 (void) gelf_getsym(data, i, &sym); 2670 2671 if (addr >= sym.st_value && 2672 addr < sym.st_value + sym.st_size && 2673 (!found || sym.st_value > osym.st_value)) { 2674 osym = sym; 2675 omid = mid; 2676 oid = i; 2677 found = 1; 2678 } 2679 2680 if (addr < sym.st_value) 2681 max = mid - 1; 2682 else 2683 min = mid + 1; 2684 } 2685 2686 if (!found) 2687 return (NULL); 2688 2689 /* 2690 * There may be many symbols with identical values so we walk 2691 * backward in the byaddr table to find the best match. 2692 */ 2693 do { 2694 sym = osym; 2695 i = oid; 2696 2697 if (omid == 0) 2698 break; 2699 2700 oid = byaddr[--omid]; 2701 (void) gelf_getsym(data, oid, &osym); 2702 } while (addr >= osym.st_value && 2703 addr < sym.st_value + osym.st_size && 2704 osym.st_value == sym.st_value); 2705 2706 *symp = sym; 2707 if (idp != NULL) 2708 *idp = i; 2709 return (symp); 2710 } 2711 2712 /* 2713 * Look up a symbol by name in the specified symbol table. 2714 */ 2715 static GElf_Sym * 2716 sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp) 2717 { 2718 Elf_Data *data = symtab->sym_data; 2719 char *strs = symtab->sym_strs; 2720 uint_t i, *byname = symtab->sym_byname; 2721 int min, mid, max, cmp; 2722 2723 if (data == NULL || strs == NULL) 2724 return (NULL); 2725 2726 min = 0; 2727 max = symtab->sym_count - 1; 2728 2729 while (min <= max) { 2730 mid = (max + min) / 2; 2731 2732 i = byname[mid]; 2733 (void) gelf_getsym(data, i, symp); 2734 2735 if ((cmp = strcmp(name, strs + symp->st_name)) == 0) { 2736 if (idp != NULL) 2737 *idp = i; 2738 return (symp); 2739 } 2740 2741 if (cmp < 0) 2742 max = mid - 1; 2743 else 2744 min = mid + 1; 2745 } 2746 2747 return (NULL); 2748 } 2749 2750 /* 2751 * Search the process symbol tables looking for a symbol whose 2752 * value to value+size contain the address specified by addr. 2753 * Return values are: 2754 * sym_name_buffer containing the symbol name 2755 * GElf_Sym symbol table entry 2756 * prsyminfo_t ancillary symbol information 2757 * Returns 0 on success, -1 on failure. 2758 */ 2759 int 2760 Pxlookup_by_addr( 2761 struct ps_prochandle *P, 2762 uintptr_t addr, /* process address being sought */ 2763 char *sym_name_buffer, /* buffer for the symbol name */ 2764 size_t bufsize, /* size of sym_name_buffer */ 2765 GElf_Sym *symbolp, /* returned symbol table entry */ 2766 prsyminfo_t *sip) /* returned symbol info */ 2767 { 2768 GElf_Sym *symp; 2769 char *name; 2770 GElf_Sym sym1, *sym1p = NULL; 2771 GElf_Sym sym2, *sym2p = NULL; 2772 char *name1 = NULL; 2773 char *name2 = NULL; 2774 uint_t i1; 2775 uint_t i2; 2776 map_info_t *mptr; 2777 file_info_t *fptr; 2778 2779 (void) Prd_agent(P); 2780 2781 if ((mptr = Paddr2mptr(P, addr)) == NULL || /* no such address */ 2782 (fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */ 2783 fptr->file_elf == NULL) /* not an ELF file */ 2784 return (-1); 2785 2786 /* 2787 * Adjust the address by the load object base address in 2788 * case the address turns out to be in a shared library. 2789 */ 2790 addr -= fptr->file_dyn_base; 2791 2792 /* 2793 * Search both symbol tables, symtab first, then dynsym. 2794 */ 2795 if ((sym1p = sym_by_addr(&fptr->file_symtab, addr, &sym1, &i1)) != NULL) 2796 name1 = fptr->file_symtab.sym_strs + sym1.st_name; 2797 if ((sym2p = sym_by_addr(&fptr->file_dynsym, addr, &sym2, &i2)) != NULL) 2798 name2 = fptr->file_dynsym.sym_strs + sym2.st_name; 2799 2800 if ((symp = sym_prefer(sym1p, name1, sym2p, name2)) == NULL) 2801 return (-1); 2802 2803 name = (symp == sym1p) ? name1 : name2; 2804 if (bufsize > 0) { 2805 (void) strncpy(sym_name_buffer, name, bufsize); 2806 sym_name_buffer[bufsize - 1] = '\0'; 2807 } 2808 2809 *symbolp = *symp; 2810 if (sip != NULL) { 2811 sip->prs_name = bufsize == 0 ? NULL : sym_name_buffer; 2812 sip->prs_object = fptr->file_lbase; 2813 sip->prs_id = (symp == sym1p) ? i1 : i2; 2814 sip->prs_table = (symp == sym1p) ? PR_SYMTAB : PR_DYNSYM; 2815 sip->prs_lmid = (fptr->file_lo == NULL) ? LM_ID_BASE : 2816 fptr->file_lo->rl_lmident; 2817 } 2818 2819 if (GELF_ST_TYPE(symbolp->st_info) != STT_TLS) 2820 symbolp->st_value += fptr->file_dyn_base; 2821 2822 return (0); 2823 } 2824 2825 int 2826 Plookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf, size_t size, 2827 GElf_Sym *symp) 2828 { 2829 return (Pxlookup_by_addr(P, addr, buf, size, symp, NULL)); 2830 } 2831 2832 /* 2833 * Search the process symbol tables looking for a symbol whose name matches the 2834 * specified name and whose object and link map optionally match the specified 2835 * parameters. On success, the function returns 0 and fills in the GElf_Sym 2836 * symbol table entry. On failure, -1 is returned. 2837 */ 2838 int 2839 Pxlookup_by_name( 2840 struct ps_prochandle *P, 2841 Lmid_t lmid, /* link map to match, or -1 for any */ 2842 const char *oname, /* load object name */ 2843 const char *sname, /* symbol name */ 2844 GElf_Sym *symp, /* returned symbol table entry */ 2845 prsyminfo_t *sip) /* returned symbol info */ 2846 { 2847 map_info_t *mptr; 2848 file_info_t *fptr; 2849 int cnt; 2850 2851 GElf_Sym sym; 2852 prsyminfo_t si; 2853 int rv = -1; 2854 uint_t id; 2855 2856 if (oname == PR_OBJ_EVERY) { 2857 /* create all the file_info_t's for all the mappings */ 2858 (void) Prd_agent(P); 2859 cnt = P->num_files; 2860 fptr = list_next(&P->file_head); 2861 } else { 2862 cnt = 1; 2863 if ((mptr = object_name_to_map(P, lmid, oname)) == NULL || 2864 (fptr = build_map_symtab(P, mptr)) == NULL) 2865 return (-1); 2866 } 2867 2868 /* 2869 * Iterate through the loaded object files and look for the symbol 2870 * name in the .symtab and .dynsym of each. If we encounter a match 2871 * with SHN_UNDEF, keep looking in hopes of finding a better match. 2872 * This means that a name such as "puts" will match the puts function 2873 * in libc instead of matching the puts PLT entry in the a.out file. 2874 */ 2875 for (; cnt > 0; cnt--, fptr = list_next(fptr)) { 2876 Pbuild_file_symtab(P, fptr); 2877 2878 if (fptr->file_elf == NULL) 2879 continue; 2880 2881 if (lmid != PR_LMID_EVERY && fptr->file_lo != NULL && 2882 lmid != fptr->file_lo->rl_lmident) 2883 continue; 2884 2885 if (fptr->file_symtab.sym_data != NULL && 2886 sym_by_name(&fptr->file_symtab, sname, symp, &id)) { 2887 if (sip != NULL) { 2888 sip->prs_id = id; 2889 sip->prs_table = PR_SYMTAB; 2890 sip->prs_object = oname; 2891 sip->prs_name = sname; 2892 sip->prs_lmid = fptr->file_lo == NULL ? 2893 LM_ID_BASE : fptr->file_lo->rl_lmident; 2894 } 2895 } else if (fptr->file_dynsym.sym_data != NULL && 2896 sym_by_name(&fptr->file_dynsym, sname, symp, &id)) { 2897 if (sip != NULL) { 2898 sip->prs_id = id; 2899 sip->prs_table = PR_DYNSYM; 2900 sip->prs_object = oname; 2901 sip->prs_name = sname; 2902 sip->prs_lmid = fptr->file_lo == NULL ? 2903 LM_ID_BASE : fptr->file_lo->rl_lmident; 2904 } 2905 } else { 2906 continue; 2907 } 2908 2909 if (GELF_ST_TYPE(symp->st_info) != STT_TLS) 2910 symp->st_value += fptr->file_dyn_base; 2911 2912 if (symp->st_shndx != SHN_UNDEF) 2913 return (0); 2914 2915 if (rv != 0) { 2916 if (sip != NULL) 2917 si = *sip; 2918 sym = *symp; 2919 rv = 0; 2920 } 2921 } 2922 2923 if (rv == 0) { 2924 if (sip != NULL) 2925 *sip = si; 2926 *symp = sym; 2927 } 2928 2929 return (rv); 2930 } 2931 2932 /* 2933 * Search the process symbol tables looking for a symbol whose name matches the 2934 * specified name, but without any restriction on the link map id. 2935 */ 2936 int 2937 Plookup_by_name(struct ps_prochandle *P, const char *object, 2938 const char *symbol, GElf_Sym *symp) 2939 { 2940 return (Pxlookup_by_name(P, PR_LMID_EVERY, object, symbol, symp, NULL)); 2941 } 2942 2943 /* 2944 * Iterate over the process's address space mappings. 2945 */ 2946 int 2947 Pmapping_iter(struct ps_prochandle *P, proc_map_f *func, void *cd) 2948 { 2949 map_info_t *mptr; 2950 file_info_t *fptr; 2951 char *object_name; 2952 int rc = 0; 2953 int i; 2954 2955 /* create all the file_info_t's for all the mappings */ 2956 (void) Prd_agent(P); 2957 2958 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) { 2959 if ((fptr = mptr->map_file) == NULL) 2960 object_name = NULL; 2961 else 2962 object_name = fptr->file_lname; 2963 if ((rc = func(cd, &mptr->map_pmap, object_name)) != 0) 2964 return (rc); 2965 } 2966 return (0); 2967 } 2968 2969 /* 2970 * Iterate over the process's mapped objects. 2971 */ 2972 int 2973 Pobject_iter(struct ps_prochandle *P, proc_map_f *func, void *cd) 2974 { 2975 map_info_t *mptr; 2976 file_info_t *fptr; 2977 uint_t cnt; 2978 int rc = 0; 2979 2980 (void) Prd_agent(P); /* create file_info_t's for all the mappings */ 2981 Pupdate_maps(P); 2982 2983 for (cnt = P->num_files, fptr = list_next(&P->file_head); 2984 cnt; cnt--, fptr = list_next(fptr)) { 2985 2986 const char *lname = fptr->file_lname ? fptr->file_lname : ""; 2987 2988 if ((mptr = fptr->file_map) == NULL) 2989 continue; 2990 2991 if ((rc = func(cd, &mptr->map_pmap, lname)) != 0) 2992 return (rc); 2993 } 2994 return (0); 2995 } 2996 2997 /* 2998 * Given a virtual address, return the name of the underlying 2999 * mapped object (file), as provided by the dynamic linker. 3000 * Return NULL on failure (no underlying shared library). 3001 */ 3002 char * 3003 Pobjname(struct ps_prochandle *P, uintptr_t addr, 3004 char *buffer, size_t bufsize) 3005 { 3006 map_info_t *mptr; 3007 file_info_t *fptr; 3008 3009 /* create all the file_info_t's for all the mappings */ 3010 (void) Prd_agent(P); 3011 3012 if ((mptr = Paddr2mptr(P, addr)) != NULL && 3013 (fptr = mptr->map_file) != NULL && 3014 fptr->file_lname != NULL) { 3015 (void) strncpy(buffer, fptr->file_lname, bufsize); 3016 if (strlen(fptr->file_lname) >= bufsize) 3017 buffer[bufsize-1] = '\0'; 3018 return (buffer); 3019 } 3020 return (NULL); 3021 } 3022 3023 /* 3024 * Given a virtual address, return the link map id of the underlying mapped 3025 * object (file), as provided by the dynamic linker. Return -1 on failure. 3026 */ 3027 int 3028 Plmid(struct ps_prochandle *P, uintptr_t addr, Lmid_t *lmidp) 3029 { 3030 map_info_t *mptr; 3031 file_info_t *fptr; 3032 3033 /* create all the file_info_t's for all the mappings */ 3034 (void) Prd_agent(P); 3035 3036 if ((mptr = Paddr2mptr(P, addr)) != NULL && 3037 (fptr = mptr->map_file) != NULL && fptr->file_lo != NULL) { 3038 *lmidp = fptr->file_lo->rl_lmident; 3039 return (0); 3040 } 3041 3042 return (-1); 3043 } 3044 3045 /* 3046 * Given an object name and optional lmid, iterate over the object's symbols. 3047 * If which == PR_SYMTAB, search the normal symbol table. 3048 * If which == PR_DYNSYM, search the dynamic symbol table. 3049 */ 3050 static int 3051 Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name, 3052 int which, int mask, pr_order_t order, proc_xsym_f *func, void *cd) 3053 { 3054 GElf_Sym sym; 3055 GElf_Shdr shdr; 3056 map_info_t *mptr; 3057 file_info_t *fptr; 3058 sym_tbl_t *symtab; 3059 Elf_Data *data; 3060 size_t symn; 3061 const char *strs; 3062 size_t strsz; 3063 prsyminfo_t si; 3064 int rv; 3065 uint_t *map, i, count, ndx; 3066 3067 if ((mptr = object_name_to_map(P, lmid, object_name)) == NULL) 3068 return (-1); 3069 3070 if ((fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */ 3071 fptr->file_elf == NULL) /* not an ELF file */ 3072 return (-1); 3073 3074 /* 3075 * Search the specified symbol table. 3076 */ 3077 switch (which) { 3078 case PR_SYMTAB: 3079 symtab = &fptr->file_symtab; 3080 si.prs_table = PR_SYMTAB; 3081 break; 3082 case PR_DYNSYM: 3083 symtab = &fptr->file_dynsym; 3084 si.prs_table = PR_DYNSYM; 3085 break; 3086 default: 3087 return (-1); 3088 } 3089 3090 si.prs_object = object_name; 3091 si.prs_lmid = fptr->file_lo == NULL ? 3092 LM_ID_BASE : fptr->file_lo->rl_lmident; 3093 3094 data = symtab->sym_data; 3095 symn = symtab->sym_symn; 3096 strs = symtab->sym_strs; 3097 strsz = symtab->sym_strsz; 3098 3099 if (data == NULL || strs == NULL) 3100 return (-1); 3101 3102 switch (order) { 3103 case PRO_NATURAL: 3104 map = NULL; 3105 count = symn; 3106 break; 3107 case PRO_BYNAME: 3108 map = symtab->sym_byname; 3109 count = symtab->sym_count; 3110 break; 3111 case PRO_BYADDR: 3112 map = symtab->sym_byaddr; 3113 count = symtab->sym_count; 3114 break; 3115 default: 3116 return (-1); 3117 } 3118 3119 rv = 0; 3120 3121 for (i = 0; i < count; i++) { 3122 ndx = map == NULL ? i : map[i]; 3123 if (gelf_getsym(data, ndx, &sym) != NULL) { 3124 uint_t s_bind, s_type, type; 3125 3126 if (sym.st_name >= strsz) /* invalid st_name */ 3127 continue; 3128 3129 s_bind = GELF_ST_BIND(sym.st_info); 3130 s_type = GELF_ST_TYPE(sym.st_info); 3131 3132 /* 3133 * In case you haven't already guessed, this relies on 3134 * the bitmask used in <libproc.h> for encoding symbol 3135 * type and binding matching the order of STB and STT 3136 * constants in <sys/elf.h>. ELF can't change without 3137 * breaking binary compatibility, so I think this is 3138 * reasonably fair game. 3139 */ 3140 if (s_bind < STB_NUM && s_type < STT_NUM) { 3141 type = (1 << (s_type + 8)) | (1 << s_bind); 3142 if ((type & ~mask) != 0) 3143 continue; 3144 } else 3145 continue; /* Invalid type or binding */ 3146 3147 if (GELF_ST_TYPE(sym.st_info) != STT_TLS) 3148 sym.st_value += fptr->file_dyn_base; 3149 3150 si.prs_name = strs + sym.st_name; 3151 3152 /* 3153 * If symbol's type is STT_SECTION, then try to lookup 3154 * the name of the corresponding section. 3155 */ 3156 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && 3157 fptr->file_shstrs != NULL && 3158 gelf_getshdr(elf_getscn(fptr->file_elf, 3159 sym.st_shndx), &shdr) != NULL && 3160 shdr.sh_name != 0 && 3161 shdr.sh_name < fptr->file_shstrsz) 3162 si.prs_name = fptr->file_shstrs + shdr.sh_name; 3163 3164 si.prs_id = ndx; 3165 if ((rv = func(cd, &sym, si.prs_name, &si)) != 0) 3166 break; 3167 } 3168 } 3169 3170 return (rv); 3171 } 3172 3173 int 3174 Pxsymbol_iter(struct ps_prochandle *P, Lmid_t lmid, const char *object_name, 3175 int which, int mask, proc_xsym_f *func, void *cd) 3176 { 3177 return (Psymbol_iter_com(P, lmid, object_name, which, mask, 3178 PRO_NATURAL, func, cd)); 3179 } 3180 3181 int 3182 Psymbol_iter_by_lmid(struct ps_prochandle *P, Lmid_t lmid, 3183 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3184 { 3185 return (Psymbol_iter_com(P, lmid, object_name, which, mask, 3186 PRO_NATURAL, (proc_xsym_f *)func, cd)); 3187 } 3188 3189 int 3190 Psymbol_iter(struct ps_prochandle *P, 3191 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3192 { 3193 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3194 PRO_NATURAL, (proc_xsym_f *)func, cd)); 3195 } 3196 3197 int 3198 Psymbol_iter_by_addr(struct ps_prochandle *P, 3199 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3200 { 3201 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3202 PRO_BYADDR, (proc_xsym_f *)func, cd)); 3203 } 3204 3205 int 3206 Psymbol_iter_by_name(struct ps_prochandle *P, 3207 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3208 { 3209 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3210 PRO_BYNAME, (proc_xsym_f *)func, cd)); 3211 } 3212 3213 /* 3214 * Get the platform string from the core file if we have it; 3215 * just perform the system call for the caller if this is a live process. 3216 */ 3217 char * 3218 Pplatform(struct ps_prochandle *P, char *s, size_t n) 3219 { 3220 if (P->state == PS_IDLE) { 3221 errno = ENODATA; 3222 return (NULL); 3223 } 3224 3225 if (P->state == PS_DEAD) { 3226 if (P->core->core_platform == NULL) { 3227 errno = ENODATA; 3228 return (NULL); 3229 } 3230 (void) strncpy(s, P->core->core_platform, n - 1); 3231 s[n - 1] = '\0'; 3232 3233 } else if (sysinfo(SI_PLATFORM, s, n) == -1) 3234 return (NULL); 3235 3236 return (s); 3237 } 3238 3239 /* 3240 * Get the uname(2) information from the core file if we have it; 3241 * just perform the system call for the caller if this is a live process. 3242 */ 3243 int 3244 Puname(struct ps_prochandle *P, struct utsname *u) 3245 { 3246 if (P->state == PS_IDLE) { 3247 errno = ENODATA; 3248 return (-1); 3249 } 3250 3251 if (P->state == PS_DEAD) { 3252 if (P->core->core_uts == NULL) { 3253 errno = ENODATA; 3254 return (-1); 3255 } 3256 (void) memcpy(u, P->core->core_uts, sizeof (struct utsname)); 3257 return (0); 3258 } 3259 return (uname(u)); 3260 } 3261 3262 /* 3263 * Get the zone name from the core file if we have it; look up the 3264 * name based on the zone id if this is a live process. 3265 */ 3266 char * 3267 Pzonename(struct ps_prochandle *P, char *s, size_t n) 3268 { 3269 if (P->state == PS_IDLE) { 3270 errno = ENODATA; 3271 return (NULL); 3272 } 3273 3274 if (P->state == PS_DEAD) { 3275 if (P->core->core_zonename == NULL) { 3276 errno = ENODATA; 3277 return (NULL); 3278 } 3279 (void) strlcpy(s, P->core->core_zonename, n); 3280 } else { 3281 if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0) 3282 return (NULL); 3283 s[n - 1] = '\0'; 3284 } 3285 return (s); 3286 } 3287 3288 /* 3289 * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize 3290 * the symbol table heads in the new ps_prochandle. 3291 */ 3292 void 3293 Pinitsym(struct ps_prochandle *P) 3294 { 3295 P->num_files = 0; 3296 list_link(&P->file_head, NULL); 3297 } 3298 3299 /* 3300 * Called from Prelease() to destroy the symbol tables. 3301 * Must be called by the client after an exec() in the victim process. 3302 */ 3303 void 3304 Preset_maps(struct ps_prochandle *P) 3305 { 3306 int i; 3307 3308 if (P->rap != NULL) { 3309 rd_delete(P->rap); 3310 P->rap = NULL; 3311 } 3312 3313 if (P->execname != NULL) { 3314 free(P->execname); 3315 P->execname = NULL; 3316 } 3317 3318 if (P->auxv != NULL) { 3319 free(P->auxv); 3320 P->auxv = NULL; 3321 P->nauxv = 0; 3322 } 3323 3324 for (i = 0; i < P->map_count; i++) 3325 map_info_free(P, &P->mappings[i]); 3326 3327 if (P->mappings != NULL) { 3328 free(P->mappings); 3329 P->mappings = NULL; 3330 } 3331 P->map_count = P->map_alloc = 0; 3332 3333 P->info_valid = 0; 3334 } 3335 3336 typedef struct getenv_data { 3337 char *buf; 3338 size_t bufsize; 3339 const char *search; 3340 size_t searchlen; 3341 } getenv_data_t; 3342 3343 /*ARGSUSED*/ 3344 static int 3345 getenv_func(void *data, struct ps_prochandle *P, uintptr_t addr, 3346 const char *nameval) 3347 { 3348 getenv_data_t *d = data; 3349 size_t len; 3350 3351 if (nameval == NULL) 3352 return (0); 3353 3354 if (d->searchlen < strlen(nameval) && 3355 strncmp(nameval, d->search, d->searchlen) == 0 && 3356 nameval[d->searchlen] == '=') { 3357 len = MIN(strlen(nameval), d->bufsize - 1); 3358 (void) strncpy(d->buf, nameval, len); 3359 d->buf[len] = '\0'; 3360 return (1); 3361 } 3362 3363 return (0); 3364 } 3365 3366 char * 3367 Pgetenv(struct ps_prochandle *P, const char *name, char *buf, size_t buflen) 3368 { 3369 getenv_data_t d; 3370 3371 d.buf = buf; 3372 d.bufsize = buflen; 3373 d.search = name; 3374 d.searchlen = strlen(name); 3375 3376 if (Penv_iter(P, getenv_func, &d) == 1) { 3377 char *equals = strchr(d.buf, '='); 3378 3379 if (equals != NULL) { 3380 (void) memmove(d.buf, equals + 1, 3381 d.buf + buflen - equals - 1); 3382 d.buf[d.buf + buflen - equals] = '\0'; 3383 3384 return (buf); 3385 } 3386 } 3387 3388 return (NULL); 3389 } 3390 3391 /* number of argument or environment pointers to read all at once */ 3392 #define NARG 100 3393 3394 int 3395 Penv_iter(struct ps_prochandle *P, proc_env_f *func, void *data) 3396 { 3397 const psinfo_t *psp; 3398 uintptr_t envpoff; 3399 GElf_Sym sym; 3400 int ret; 3401 char *buf, *nameval; 3402 size_t buflen; 3403 3404 int nenv = NARG; 3405 long envp[NARG]; 3406 3407 /* 3408 * Attempt to find the "_environ" variable in the process. 3409 * Failing that, use the original value provided by Ppsinfo(). 3410 */ 3411 if ((psp = Ppsinfo(P)) == NULL) 3412 return (-1); 3413 3414 envpoff = psp->pr_envp; /* Default if no _environ found */ 3415 3416 if (Plookup_by_name(P, PR_OBJ_EXEC, "_environ", &sym) == 0) { 3417 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 3418 if (Pread(P, &envpoff, sizeof (envpoff), 3419 sym.st_value) != sizeof (envpoff)) 3420 envpoff = psp->pr_envp; 3421 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) { 3422 uint32_t envpoff32; 3423 3424 if (Pread(P, &envpoff32, sizeof (envpoff32), 3425 sym.st_value) != sizeof (envpoff32)) 3426 envpoff = psp->pr_envp; 3427 else 3428 envpoff = envpoff32; 3429 } 3430 } 3431 3432 buflen = 128; 3433 buf = malloc(buflen); 3434 3435 ret = 0; 3436 for (;;) { 3437 uintptr_t envoff; 3438 3439 if (nenv == NARG) { 3440 (void) memset(envp, 0, sizeof (envp)); 3441 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 3442 if (Pread(P, envp, 3443 sizeof (envp), envpoff) <= 0) { 3444 ret = -1; 3445 break; 3446 } 3447 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) { 3448 uint32_t e32[NARG]; 3449 int i; 3450 3451 (void) memset(e32, 0, sizeof (e32)); 3452 if (Pread(P, e32, sizeof (e32), envpoff) <= 0) { 3453 ret = -1; 3454 break; 3455 } 3456 for (i = 0; i < NARG; i++) 3457 envp[i] = e32[i]; 3458 } 3459 nenv = 0; 3460 } 3461 3462 if ((envoff = envp[nenv++]) == NULL) 3463 break; 3464 3465 /* 3466 * Attempt to read the string from the process. 3467 */ 3468 again: 3469 ret = Pread_string(P, buf, buflen, envoff); 3470 3471 if (ret <= 0) { 3472 nameval = NULL; 3473 } else if (ret == buflen - 1) { 3474 free(buf); 3475 /* 3476 * Bail if we have a corrupted environment 3477 */ 3478 if (buflen >= ARG_MAX) 3479 return (-1); 3480 buflen *= 2; 3481 buf = malloc(buflen); 3482 goto again; 3483 } else { 3484 nameval = buf; 3485 } 3486 3487 if ((ret = func(data, P, envoff, nameval)) != 0) 3488 break; 3489 3490 envpoff += (P->status.pr_dmodel == PR_MODEL_LP64)? 8 : 4; 3491 } 3492 3493 free(buf); 3494 3495 return (ret); 3496 } 3497