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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 name with fewer leading underscores in the name. 2007 */ 2008 while (*aname == '_' && *bname == '_') { 2009 aname++; 2010 bname++; 2011 } 2012 2013 if (*bname == '_') 2014 return (-1); 2015 if (*aname == '_') 2016 return (1); 2017 2018 /* 2019 * Prefer the symbol with the smaller size. 2020 */ 2021 if (a->st_size < b->st_size) 2022 return (-1); 2023 if (a->st_size > b->st_size) 2024 return (1); 2025 2026 /* 2027 * All other factors being equal, fall back to lexicographic order. 2028 */ 2029 return (strcmp(aname, bname)); 2030 } 2031 2032 static int 2033 byaddr_cmp(const void *aa, const void *bb) 2034 { 2035 GElf_Sym *a = &sort_syms[*(uint_t *)aa]; 2036 GElf_Sym *b = &sort_syms[*(uint_t *)bb]; 2037 char *aname = sort_strs + a->st_name; 2038 char *bname = sort_strs + b->st_name; 2039 2040 return (byaddr_cmp_common(a, aname, b, bname)); 2041 } 2042 2043 static int 2044 byname_cmp(const void *aa, const void *bb) 2045 { 2046 GElf_Sym *a = &sort_syms[*(uint_t *)aa]; 2047 GElf_Sym *b = &sort_syms[*(uint_t *)bb]; 2048 char *aname = sort_strs + a->st_name; 2049 char *bname = sort_strs + b->st_name; 2050 2051 return (strcmp(aname, bname)); 2052 } 2053 2054 void 2055 optimize_symtab(sym_tbl_t *symtab) 2056 { 2057 GElf_Sym *symp, *syms; 2058 uint_t i, *indexa, *indexb; 2059 Elf_Data *data; 2060 size_t symn, strsz, count; 2061 2062 if (symtab == NULL || symtab->sym_data == NULL || 2063 symtab->sym_byaddr != NULL) 2064 return; 2065 2066 data = symtab->sym_data; 2067 symn = symtab->sym_symn; 2068 strsz = symtab->sym_strsz; 2069 2070 symp = syms = malloc(sizeof (GElf_Sym) * symn); 2071 2072 /* 2073 * First record all the symbols into a table and count up the ones 2074 * that we're interested in. We mark symbols as invalid by setting 2075 * the st_name to an illegal value. 2076 */ 2077 for (i = 0, count = 0; i < symn; i++, symp++) { 2078 if (gelf_getsym(data, i, symp) != NULL && 2079 symp->st_name < strsz && 2080 IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info))) 2081 count++; 2082 else 2083 symp->st_name = strsz; 2084 } 2085 2086 /* 2087 * Allocate sufficient space for both tables and populate them 2088 * with the same symbols we just counted. 2089 */ 2090 symtab->sym_count = count; 2091 indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count); 2092 indexb = symtab->sym_byname = calloc(sizeof (uint_t), count); 2093 2094 for (i = 0, symp = syms; i < symn; i++, symp++) { 2095 if (symp->st_name < strsz) 2096 *indexa++ = *indexb++ = i; 2097 } 2098 2099 /* 2100 * Sort the two tables according to the appropriate criteria. 2101 */ 2102 (void) mutex_lock(&sort_mtx); 2103 sort_strs = symtab->sym_strs; 2104 sort_syms = syms; 2105 2106 qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp); 2107 qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp); 2108 2109 sort_strs = NULL; 2110 sort_syms = NULL; 2111 (void) mutex_unlock(&sort_mtx); 2112 2113 free(syms); 2114 } 2115 2116 /* 2117 * Build the symbol table for the given mapped file. 2118 */ 2119 void 2120 Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr) 2121 { 2122 char objectfile[PATH_MAX]; 2123 uint_t i; 2124 2125 GElf_Ehdr ehdr; 2126 GElf_Sym s; 2127 2128 Elf_Data *shdata; 2129 Elf_Scn *scn; 2130 Elf *elf; 2131 size_t nshdrs, shstrndx; 2132 2133 struct { 2134 GElf_Shdr c_shdr; 2135 Elf_Data *c_data; 2136 const char *c_name; 2137 } *cp, *cache = NULL, *dyn = NULL, *plt = NULL, *ctf = NULL; 2138 2139 if (fptr->file_init) 2140 return; /* We've already processed this file */ 2141 2142 /* 2143 * Mark the file_info struct as having the symbol table initialized 2144 * even if we fail below. We tried once; we don't try again. 2145 */ 2146 fptr->file_init = 1; 2147 2148 if (elf_version(EV_CURRENT) == EV_NONE) { 2149 dprintf("libproc ELF version is more recent than libelf\n"); 2150 return; 2151 } 2152 2153 if (P->state == PS_DEAD || P->state == PS_IDLE) { 2154 /* 2155 * If we're a not live, we can't open files from the /proc 2156 * object directory; we have only the mapping and file names 2157 * to guide us. We prefer the file_lname, but need to handle 2158 * the case of it being NULL in order to bootstrap: we first 2159 * come here during rd_new() when the only information we have 2160 * is interpreter name associated with the AT_BASE mapping. 2161 */ 2162 (void) snprintf(objectfile, sizeof (objectfile), "%s", 2163 fptr->file_lname ? fptr->file_lname : fptr->file_pname); 2164 } else { 2165 (void) snprintf(objectfile, sizeof (objectfile), 2166 "/proc/%d/object/%s", (int)P->pid, fptr->file_pname); 2167 } 2168 2169 /* 2170 * Open the object file, create the elf file, and then get the elf 2171 * header and .shstrtab data buffer so we can process sections by 2172 * name. If anything goes wrong try to fake up an elf file from 2173 * the in-core elf image. 2174 */ 2175 if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) { 2176 dprintf("Pbuild_file_symtab: failed to open %s: %s\n", 2177 objectfile, strerror(errno)); 2178 2179 if ((elf = fake_elf(P, fptr)) == NULL || 2180 elf_kind(elf) != ELF_K_ELF || 2181 gelf_getehdr(elf, &ehdr) == NULL || 2182 elf_getshnum(elf, &nshdrs) == 0 || 2183 elf_getshstrndx(elf, &shstrndx) == 0 || 2184 (scn = elf_getscn(elf, shstrndx)) == NULL || 2185 (shdata = elf_getdata(scn, NULL)) == NULL) { 2186 dprintf("failed to fake up ELF file\n"); 2187 return; 2188 } 2189 2190 } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL || 2191 elf_kind(elf) != ELF_K_ELF || 2192 gelf_getehdr(elf, &ehdr) == NULL || 2193 elf_getshnum(elf, &nshdrs) == 0 || 2194 elf_getshstrndx(elf, &shstrndx) == 0 || 2195 (scn = elf_getscn(elf, shstrndx)) == NULL || 2196 (shdata = elf_getdata(scn, NULL)) == NULL) { 2197 dprintf("failed to process ELF file %s: %s\n", 2198 objectfile, elf_errmsg(elf_errno())); 2199 2200 if ((elf = fake_elf(P, fptr)) == NULL || 2201 elf_kind(elf) != ELF_K_ELF || 2202 gelf_getehdr(elf, &ehdr) == NULL || 2203 elf_getshnum(elf, &nshdrs) == 0 || 2204 elf_getshstrndx(elf, &shstrndx) == 0 || 2205 (scn = elf_getscn(elf, shstrndx)) == NULL || 2206 (shdata = elf_getdata(scn, NULL)) == NULL) { 2207 dprintf("failed to fake up ELF file\n"); 2208 goto bad; 2209 } 2210 2211 } else if (file_differs(P, elf, fptr)) { 2212 Elf *newelf; 2213 2214 /* 2215 * Before we get too excited about this elf file, we'll check 2216 * its checksum value against the value we have in memory. If 2217 * they don't agree, we try to fake up a new elf file and 2218 * proceed with that instead. 2219 */ 2220 2221 dprintf("ELF file %s (%lx) doesn't match in-core image\n", 2222 fptr->file_pname, 2223 (ulong_t)fptr->file_map->map_pmap.pr_vaddr); 2224 2225 if ((newelf = fake_elf(P, fptr)) == NULL || 2226 elf_kind(newelf) != ELF_K_ELF || 2227 gelf_getehdr(newelf, &ehdr) == NULL || 2228 elf_getshnum(newelf, &nshdrs) == 0 || 2229 elf_getshstrndx(newelf, &shstrndx) == 0 || 2230 (scn = elf_getscn(newelf, shstrndx)) == NULL || 2231 (shdata = elf_getdata(scn, NULL)) == NULL) { 2232 dprintf("failed to fake up ELF file\n"); 2233 } else { 2234 (void) elf_end(elf); 2235 elf = newelf; 2236 2237 dprintf("switched to faked up ELF file\n"); 2238 } 2239 } 2240 2241 if ((cache = malloc(nshdrs * sizeof (*cache))) == NULL) { 2242 dprintf("failed to malloc section cache for %s\n", objectfile); 2243 goto bad; 2244 } 2245 2246 dprintf("processing ELF file %s\n", objectfile); 2247 fptr->file_class = ehdr.e_ident[EI_CLASS]; 2248 fptr->file_etype = ehdr.e_type; 2249 fptr->file_elf = elf; 2250 2251 /* 2252 * Iterate through each section, caching its section header, data 2253 * pointer, and name. We use this for handling sh_link values below. 2254 */ 2255 for (cp = cache + 1, scn = NULL; scn = elf_nextscn(elf, scn); cp++) { 2256 if (gelf_getshdr(scn, &cp->c_shdr) == NULL) 2257 goto bad; /* Failed to get section header */ 2258 2259 if ((cp->c_data = elf_getdata(scn, NULL)) == NULL) 2260 goto bad; /* Failed to get section data */ 2261 2262 if (cp->c_shdr.sh_name >= shdata->d_size) 2263 goto bad; /* Corrupt section name */ 2264 2265 cp->c_name = (const char *)shdata->d_buf + cp->c_shdr.sh_name; 2266 } 2267 2268 /* 2269 * Now iterate through the section cache in order to locate info 2270 * for the .symtab, .dynsym, .dynamic, .plt, and .SUNW_ctf sections: 2271 */ 2272 for (i = 1, cp = cache + 1; i < nshdrs; i++, cp++) { 2273 GElf_Shdr *shp = &cp->c_shdr; 2274 2275 if (shp->sh_type == SHT_SYMTAB || shp->sh_type == SHT_DYNSYM) { 2276 sym_tbl_t *symp = shp->sh_type == SHT_SYMTAB ? 2277 &fptr->file_symtab : &fptr->file_dynsym; 2278 2279 /* 2280 * It's possible that the we already got the symbol 2281 * table from the core file itself. Either the file 2282 * differs in which case our faked up elf file will 2283 * only contain the dynsym (not the symtab) or the 2284 * file matches in which case we'll just be replacing 2285 * the symbol table we pulled out of the core file 2286 * with an equivalent one. In either case, this 2287 * check isn't essential, but it's a good idea. 2288 */ 2289 if (symp->sym_data == NULL) { 2290 symp->sym_data = cp->c_data; 2291 symp->sym_symn = shp->sh_size / shp->sh_entsize; 2292 symp->sym_strs = 2293 cache[shp->sh_link].c_data->d_buf; 2294 symp->sym_strsz = 2295 cache[shp->sh_link].c_data->d_size; 2296 symp->sym_hdr = cp->c_shdr; 2297 symp->sym_strhdr = cache[shp->sh_link].c_shdr; 2298 } 2299 2300 } else if (shp->sh_type == SHT_DYNAMIC) { 2301 dyn = cp; 2302 2303 } else if (strcmp(cp->c_name, ".plt") == 0) { 2304 plt = cp; 2305 2306 } else if (strcmp(cp->c_name, ".SUNW_ctf") == 0) { 2307 /* 2308 * Skip over bogus CTF sections so they don't come back 2309 * to haunt us later. 2310 */ 2311 if (shp->sh_link == 0 || 2312 shp->sh_link >= nshdrs || 2313 (cache[shp->sh_link].c_shdr.sh_type != SHT_DYNSYM && 2314 cache[shp->sh_link].c_shdr.sh_type != SHT_SYMTAB)) { 2315 dprintf("Bad sh_link %d for " 2316 "CTF\n", shp->sh_link); 2317 continue; 2318 } 2319 ctf = cp; 2320 } 2321 } 2322 2323 /* 2324 * At this point, we've found all the symbol tables we're ever going 2325 * to find: the ones in the loop above and possibly the symtab that 2326 * was included in the core file. Before we perform any lookups, we 2327 * create sorted versions to optimize for lookups. 2328 */ 2329 optimize_symtab(&fptr->file_symtab); 2330 optimize_symtab(&fptr->file_dynsym); 2331 2332 /* 2333 * Fill in the base address of the text mapping for shared libraries. 2334 * This allows us to translate symbols before librtld_db is ready. 2335 */ 2336 if (fptr->file_etype == ET_DYN) { 2337 fptr->file_dyn_base = fptr->file_map->map_pmap.pr_vaddr - 2338 fptr->file_map->map_pmap.pr_offset; 2339 dprintf("setting file_dyn_base for %s to %p\n", 2340 objectfile, (void *)fptr->file_dyn_base); 2341 } 2342 2343 /* 2344 * Record the CTF section information in the file info structure. 2345 */ 2346 if (ctf != NULL) { 2347 fptr->file_ctf_off = ctf->c_shdr.sh_offset; 2348 fptr->file_ctf_size = ctf->c_shdr.sh_size; 2349 if (ctf->c_shdr.sh_link != 0 && 2350 cache[ctf->c_shdr.sh_link].c_shdr.sh_type == SHT_DYNSYM) 2351 fptr->file_ctf_dyn = 1; 2352 } 2353 2354 if (fptr->file_lo == NULL) 2355 goto done; /* Nothing else to do if no load object info */ 2356 2357 /* 2358 * If the object is a shared library and we have a different rl_base 2359 * value, reset file_dyn_base according to librtld_db's information. 2360 */ 2361 if (fptr->file_etype == ET_DYN && 2362 fptr->file_lo->rl_base != fptr->file_dyn_base) { 2363 dprintf("resetting file_dyn_base for %s to %p\n", 2364 objectfile, (void *)fptr->file_lo->rl_base); 2365 fptr->file_dyn_base = fptr->file_lo->rl_base; 2366 } 2367 2368 /* 2369 * Fill in the PLT information for this file if a PLT symbol is found. 2370 */ 2371 if (sym_by_name(&fptr->file_dynsym, "_PROCEDURE_LINKAGE_TABLE_", &s, 2372 NULL) != NULL) { 2373 fptr->file_plt_base = s.st_value + fptr->file_dyn_base; 2374 fptr->file_plt_size = (plt != NULL) ? plt->c_shdr.sh_size : 0; 2375 2376 /* 2377 * Bring the load object up to date; it is the only way the 2378 * user has to access the PLT data. The PLT information in the 2379 * rd_loadobj_t is not set in the call to map_iter() (the 2380 * callback for rd_loadobj_iter) where we set file_lo. 2381 */ 2382 fptr->file_lo->rl_plt_base = fptr->file_plt_base; 2383 fptr->file_lo->rl_plt_size = fptr->file_plt_size; 2384 2385 dprintf("PLT found at %p, size = %lu\n", 2386 (void *)fptr->file_plt_base, (ulong_t)fptr->file_plt_size); 2387 } 2388 2389 /* 2390 * Fill in the PLT information. 2391 */ 2392 if (dyn != NULL) { 2393 uintptr_t dynaddr = dyn->c_shdr.sh_addr + fptr->file_dyn_base; 2394 size_t ndyn = dyn->c_shdr.sh_size / dyn->c_shdr.sh_entsize; 2395 GElf_Dyn d; 2396 2397 for (i = 0; i < ndyn; i++) { 2398 if (gelf_getdyn(dyn->c_data, i, &d) != NULL && 2399 d.d_tag == DT_JMPREL) { 2400 fptr->file_jmp_rel = 2401 d.d_un.d_ptr + fptr->file_dyn_base; 2402 break; 2403 } 2404 } 2405 2406 dprintf("_DYNAMIC found at %p, %lu entries, DT_JMPREL = %p\n", 2407 (void *)dynaddr, (ulong_t)ndyn, (void *)fptr->file_jmp_rel); 2408 } 2409 2410 done: 2411 free(cache); 2412 return; 2413 2414 bad: 2415 if (cache != NULL) 2416 free(cache); 2417 2418 (void) elf_end(elf); 2419 fptr->file_elf = NULL; 2420 if (fptr->file_elfmem != NULL) { 2421 free(fptr->file_elfmem); 2422 fptr->file_elfmem = NULL; 2423 } 2424 (void) close(fptr->file_fd); 2425 fptr->file_fd = -1; 2426 } 2427 2428 /* 2429 * Given a process virtual address, return the map_info_t containing it. 2430 * If none found, return NULL. 2431 */ 2432 map_info_t * 2433 Paddr2mptr(struct ps_prochandle *P, uintptr_t addr) 2434 { 2435 int lo = 0; 2436 int hi = P->map_count - 1; 2437 int mid; 2438 map_info_t *mp; 2439 2440 while (lo <= hi) { 2441 2442 mid = (lo + hi) / 2; 2443 mp = &P->mappings[mid]; 2444 2445 /* check that addr is in [vaddr, vaddr + size) */ 2446 if ((addr - mp->map_pmap.pr_vaddr) < mp->map_pmap.pr_size) 2447 return (mp); 2448 2449 if (addr < mp->map_pmap.pr_vaddr) 2450 hi = mid - 1; 2451 else 2452 lo = mid + 1; 2453 } 2454 2455 return (NULL); 2456 } 2457 2458 /* 2459 * Return the map_info_t for the executable file. 2460 * If not found, return NULL. 2461 */ 2462 static map_info_t * 2463 exec_map(struct ps_prochandle *P) 2464 { 2465 uint_t i; 2466 map_info_t *mptr; 2467 map_info_t *mold = NULL; 2468 file_info_t *fptr; 2469 uintptr_t base; 2470 2471 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) { 2472 if (mptr->map_pmap.pr_mapname[0] == '\0') 2473 continue; 2474 if (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) { 2475 if ((fptr = mptr->map_file) != NULL && 2476 fptr->file_lo != NULL) { 2477 base = fptr->file_lo->rl_base; 2478 if (base >= mptr->map_pmap.pr_vaddr && 2479 base < mptr->map_pmap.pr_vaddr + 2480 mptr->map_pmap.pr_size) /* text space */ 2481 return (mptr); 2482 mold = mptr; /* must be the data */ 2483 continue; 2484 } 2485 /* This is a poor way to test for text space */ 2486 if (!(mptr->map_pmap.pr_mflags & MA_EXEC) || 2487 (mptr->map_pmap.pr_mflags & MA_WRITE)) { 2488 mold = mptr; 2489 continue; 2490 } 2491 return (mptr); 2492 } 2493 } 2494 2495 return (mold); 2496 } 2497 2498 /* 2499 * Given a shared object name, return the map_info_t for it. If no matching 2500 * object is found, return NULL. Normally, the link maps contain the full 2501 * object pathname, e.g. /usr/lib/libc.so.1. We allow the object name to 2502 * take one of the following forms: 2503 * 2504 * 1. An exact match (i.e. a full pathname): "/usr/lib/libc.so.1" 2505 * 2. An exact basename match: "libc.so.1" 2506 * 3. An initial basename match up to a '.' suffix: "libc.so" or "libc" 2507 * 4. The literal string "a.out" is an alias for the executable mapping 2508 * 2509 * The third case is a convenience for callers and may not be necessary. 2510 * 2511 * As the exact same object name may be loaded on different link maps (see 2512 * dlmopen(3DL)), we also allow the caller to resolve the object name by 2513 * specifying a particular link map id. If lmid is PR_LMID_EVERY, the 2514 * first matching name will be returned, regardless of the link map id. 2515 */ 2516 static map_info_t * 2517 object_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *objname) 2518 { 2519 map_info_t *mp; 2520 file_info_t *fp; 2521 size_t objlen; 2522 uint_t i; 2523 2524 /* 2525 * First pass: look for exact matches of the entire pathname or 2526 * basename (cases 1 and 2 above): 2527 */ 2528 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) { 2529 2530 if (mp->map_pmap.pr_mapname[0] == '\0' || 2531 (fp = mp->map_file) == NULL || fp->file_lname == NULL) 2532 continue; 2533 2534 if (lmid != PR_LMID_EVERY && 2535 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident)) 2536 continue; 2537 2538 /* 2539 * If we match, return the primary text mapping; otherwise 2540 * just return the mapping we matched. 2541 */ 2542 if (strcmp(fp->file_lname, objname) == 0 || 2543 strcmp(fp->file_lbase, objname) == 0) 2544 return (fp->file_map ? fp->file_map : mp); 2545 } 2546 2547 objlen = strlen(objname); 2548 2549 /* 2550 * Second pass: look for partial matches (case 3 above): 2551 */ 2552 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) { 2553 2554 if (mp->map_pmap.pr_mapname[0] == '\0' || 2555 (fp = mp->map_file) == NULL || fp->file_lname == NULL) 2556 continue; 2557 2558 if (lmid != PR_LMID_EVERY && 2559 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident)) 2560 continue; 2561 2562 /* 2563 * If we match, return the primary text mapping; otherwise 2564 * just return the mapping we matched. 2565 */ 2566 if (strncmp(fp->file_lbase, objname, objlen) == 0 && 2567 fp->file_lbase[objlen] == '.') 2568 return (fp->file_map ? fp->file_map : mp); 2569 } 2570 2571 /* 2572 * One last check: we allow "a.out" to always alias the executable, 2573 * assuming this name was not in use for something else. 2574 */ 2575 if ((lmid == PR_LMID_EVERY || lmid == LM_ID_BASE) && 2576 (strcmp(objname, "a.out") == 0)) 2577 return (P->map_exec); 2578 2579 return (NULL); 2580 } 2581 2582 static map_info_t * 2583 object_name_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name) 2584 { 2585 map_info_t *mptr; 2586 2587 if (!P->info_valid) 2588 Pupdate_maps(P); 2589 2590 if (P->map_exec == NULL && ((mptr = Paddr2mptr(P, 2591 Pgetauxval(P, AT_ENTRY))) != NULL || (mptr = exec_map(P)) != NULL)) 2592 P->map_exec = mptr; 2593 2594 if (P->map_ldso == NULL && (mptr = Paddr2mptr(P, 2595 Pgetauxval(P, AT_BASE))) != NULL) 2596 P->map_ldso = mptr; 2597 2598 if (name == PR_OBJ_EXEC) 2599 mptr = P->map_exec; 2600 else if (name == PR_OBJ_LDSO) 2601 mptr = P->map_ldso; 2602 else if (Prd_agent(P) != NULL || P->state == PS_IDLE) 2603 mptr = object_to_map(P, lmid, name); 2604 else 2605 mptr = NULL; 2606 2607 return (mptr); 2608 } 2609 2610 /* 2611 * When two symbols are found by address, decide which one is to be preferred. 2612 */ 2613 static GElf_Sym * 2614 sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2) 2615 { 2616 /* 2617 * Prefer the non-NULL symbol. 2618 */ 2619 if (sym1 == NULL) 2620 return (sym2); 2621 if (sym2 == NULL) 2622 return (sym1); 2623 2624 /* 2625 * Defer to the sort ordering... 2626 */ 2627 return (byaddr_cmp_common(sym1, name1, sym2, name2) <= 0 ? sym1 : sym2); 2628 } 2629 2630 /* 2631 * Look up a symbol by address in the specified symbol table. 2632 * Adjustment to 'addr' must already have been made for the 2633 * offset of the symbol if this is a dynamic library symbol table. 2634 */ 2635 static GElf_Sym * 2636 sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp) 2637 { 2638 Elf_Data *data = symtab->sym_data; 2639 GElf_Sym sym, osym; 2640 uint_t i, oid, *byaddr = symtab->sym_byaddr; 2641 int min, max, mid, omid, found = 0; 2642 2643 if (data == NULL) 2644 return (NULL); 2645 2646 min = 0; 2647 max = symtab->sym_count - 1; 2648 osym.st_value = 0; 2649 2650 /* 2651 * We can't return when we've found a match, we have to continue 2652 * searching for the closest matching symbol. 2653 */ 2654 while (min <= max) { 2655 mid = (max + min) / 2; 2656 2657 i = byaddr[mid]; 2658 (void) gelf_getsym(data, i, &sym); 2659 2660 if (addr >= sym.st_value && 2661 addr < sym.st_value + sym.st_size && 2662 (!found || sym.st_value > osym.st_value)) { 2663 osym = sym; 2664 omid = mid; 2665 oid = i; 2666 found = 1; 2667 } 2668 2669 if (addr < sym.st_value) 2670 max = mid - 1; 2671 else 2672 min = mid + 1; 2673 } 2674 2675 if (!found) 2676 return (NULL); 2677 2678 /* 2679 * There may be many symbols with identical values so we walk 2680 * backward in the byaddr table to find the best match. 2681 */ 2682 do { 2683 sym = osym; 2684 i = oid; 2685 2686 if (omid == 0) 2687 break; 2688 2689 oid = byaddr[--omid]; 2690 (void) gelf_getsym(data, oid, &osym); 2691 } while (addr >= osym.st_value && 2692 addr < sym.st_value + osym.st_size && 2693 osym.st_value == sym.st_value); 2694 2695 *symp = sym; 2696 if (idp != NULL) 2697 *idp = i; 2698 return (symp); 2699 } 2700 2701 /* 2702 * Look up a symbol by name in the specified symbol table. 2703 */ 2704 static GElf_Sym * 2705 sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp) 2706 { 2707 Elf_Data *data = symtab->sym_data; 2708 char *strs = symtab->sym_strs; 2709 uint_t i, *byname = symtab->sym_byname; 2710 int min, mid, max, cmp; 2711 2712 if (data == NULL || strs == NULL) 2713 return (NULL); 2714 2715 min = 0; 2716 max = symtab->sym_count - 1; 2717 2718 while (min <= max) { 2719 mid = (max + min) / 2; 2720 2721 i = byname[mid]; 2722 (void) gelf_getsym(data, i, symp); 2723 2724 if ((cmp = strcmp(name, strs + symp->st_name)) == 0) { 2725 if (idp != NULL) 2726 *idp = i; 2727 return (symp); 2728 } 2729 2730 if (cmp < 0) 2731 max = mid - 1; 2732 else 2733 min = mid + 1; 2734 } 2735 2736 return (NULL); 2737 } 2738 2739 /* 2740 * Search the process symbol tables looking for a symbol whose 2741 * value to value+size contain the address specified by addr. 2742 * Return values are: 2743 * sym_name_buffer containing the symbol name 2744 * GElf_Sym symbol table entry 2745 * prsyminfo_t ancillary symbol information 2746 * Returns 0 on success, -1 on failure. 2747 */ 2748 int 2749 Pxlookup_by_addr( 2750 struct ps_prochandle *P, 2751 uintptr_t addr, /* process address being sought */ 2752 char *sym_name_buffer, /* buffer for the symbol name */ 2753 size_t bufsize, /* size of sym_name_buffer */ 2754 GElf_Sym *symbolp, /* returned symbol table entry */ 2755 prsyminfo_t *sip) /* returned symbol info */ 2756 { 2757 GElf_Sym *symp; 2758 char *name; 2759 GElf_Sym sym1, *sym1p = NULL; 2760 GElf_Sym sym2, *sym2p = NULL; 2761 char *name1 = NULL; 2762 char *name2 = NULL; 2763 uint_t i1; 2764 uint_t i2; 2765 map_info_t *mptr; 2766 file_info_t *fptr; 2767 2768 (void) Prd_agent(P); 2769 2770 if ((mptr = Paddr2mptr(P, addr)) == NULL || /* no such address */ 2771 (fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */ 2772 fptr->file_elf == NULL) /* not an ELF file */ 2773 return (-1); 2774 2775 /* 2776 * Adjust the address by the load object base address in 2777 * case the address turns out to be in a shared library. 2778 */ 2779 addr -= fptr->file_dyn_base; 2780 2781 /* 2782 * Search both symbol tables, symtab first, then dynsym. 2783 */ 2784 if ((sym1p = sym_by_addr(&fptr->file_symtab, addr, &sym1, &i1)) != NULL) 2785 name1 = fptr->file_symtab.sym_strs + sym1.st_name; 2786 if ((sym2p = sym_by_addr(&fptr->file_dynsym, addr, &sym2, &i2)) != NULL) 2787 name2 = fptr->file_dynsym.sym_strs + sym2.st_name; 2788 2789 if ((symp = sym_prefer(sym1p, name1, sym2p, name2)) == NULL) 2790 return (-1); 2791 2792 name = (symp == sym1p) ? name1 : name2; 2793 if (bufsize > 0) { 2794 (void) strncpy(sym_name_buffer, name, bufsize); 2795 sym_name_buffer[bufsize - 1] = '\0'; 2796 } 2797 2798 *symbolp = *symp; 2799 if (sip != NULL) { 2800 sip->prs_name = bufsize == 0 ? NULL : sym_name_buffer; 2801 sip->prs_object = fptr->file_lbase; 2802 sip->prs_id = (symp == sym1p) ? i1 : i2; 2803 sip->prs_table = (symp == sym1p) ? PR_SYMTAB : PR_DYNSYM; 2804 sip->prs_lmid = (fptr->file_lo == NULL) ? LM_ID_BASE : 2805 fptr->file_lo->rl_lmident; 2806 } 2807 2808 if (GELF_ST_TYPE(symbolp->st_info) != STT_TLS) 2809 symbolp->st_value += fptr->file_dyn_base; 2810 2811 return (0); 2812 } 2813 2814 int 2815 Plookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf, size_t size, 2816 GElf_Sym *symp) 2817 { 2818 return (Pxlookup_by_addr(P, addr, buf, size, symp, NULL)); 2819 } 2820 2821 /* 2822 * Search the process symbol tables looking for a symbol whose name matches the 2823 * specified name and whose object and link map optionally match the specified 2824 * parameters. On success, the function returns 0 and fills in the GElf_Sym 2825 * symbol table entry. On failure, -1 is returned. 2826 */ 2827 int 2828 Pxlookup_by_name( 2829 struct ps_prochandle *P, 2830 Lmid_t lmid, /* link map to match, or -1 for any */ 2831 const char *oname, /* load object name */ 2832 const char *sname, /* symbol name */ 2833 GElf_Sym *symp, /* returned symbol table entry */ 2834 prsyminfo_t *sip) /* returned symbol info */ 2835 { 2836 map_info_t *mptr; 2837 file_info_t *fptr; 2838 int cnt; 2839 2840 GElf_Sym sym; 2841 prsyminfo_t si; 2842 int rv = -1; 2843 uint_t id; 2844 2845 if (oname == PR_OBJ_EVERY) { 2846 /* create all the file_info_t's for all the mappings */ 2847 (void) Prd_agent(P); 2848 cnt = P->num_files; 2849 fptr = list_next(&P->file_head); 2850 } else { 2851 cnt = 1; 2852 if ((mptr = object_name_to_map(P, lmid, oname)) == NULL || 2853 (fptr = build_map_symtab(P, mptr)) == NULL) 2854 return (-1); 2855 } 2856 2857 /* 2858 * Iterate through the loaded object files and look for the symbol 2859 * name in the .symtab and .dynsym of each. If we encounter a match 2860 * with SHN_UNDEF, keep looking in hopes of finding a better match. 2861 * This means that a name such as "puts" will match the puts function 2862 * in libc instead of matching the puts PLT entry in the a.out file. 2863 */ 2864 for (; cnt > 0; cnt--, fptr = list_next(fptr)) { 2865 Pbuild_file_symtab(P, fptr); 2866 2867 if (fptr->file_elf == NULL) 2868 continue; 2869 2870 if (lmid != PR_LMID_EVERY && fptr->file_lo != NULL && 2871 lmid != fptr->file_lo->rl_lmident) 2872 continue; 2873 2874 if (fptr->file_symtab.sym_data != NULL && 2875 sym_by_name(&fptr->file_symtab, sname, symp, &id)) { 2876 if (sip != NULL) { 2877 sip->prs_id = id; 2878 sip->prs_table = PR_SYMTAB; 2879 sip->prs_object = oname; 2880 sip->prs_name = sname; 2881 sip->prs_lmid = fptr->file_lo == NULL ? 2882 LM_ID_BASE : fptr->file_lo->rl_lmident; 2883 } 2884 } else if (fptr->file_dynsym.sym_data != NULL && 2885 sym_by_name(&fptr->file_dynsym, sname, symp, &id)) { 2886 if (sip != NULL) { 2887 sip->prs_id = id; 2888 sip->prs_table = PR_DYNSYM; 2889 sip->prs_object = oname; 2890 sip->prs_name = sname; 2891 sip->prs_lmid = fptr->file_lo == NULL ? 2892 LM_ID_BASE : fptr->file_lo->rl_lmident; 2893 } 2894 } else { 2895 continue; 2896 } 2897 2898 if (GELF_ST_TYPE(symp->st_info) != STT_TLS) 2899 symp->st_value += fptr->file_dyn_base; 2900 2901 if (symp->st_shndx != SHN_UNDEF) 2902 return (0); 2903 2904 if (rv != 0) { 2905 if (sip != NULL) 2906 si = *sip; 2907 sym = *symp; 2908 rv = 0; 2909 } 2910 } 2911 2912 if (rv == 0) { 2913 if (sip != NULL) 2914 *sip = si; 2915 *symp = sym; 2916 } 2917 2918 return (rv); 2919 } 2920 2921 /* 2922 * Search the process symbol tables looking for a symbol whose name matches the 2923 * specified name, but without any restriction on the link map id. 2924 */ 2925 int 2926 Plookup_by_name(struct ps_prochandle *P, const char *object, 2927 const char *symbol, GElf_Sym *symp) 2928 { 2929 return (Pxlookup_by_name(P, PR_LMID_EVERY, object, symbol, symp, NULL)); 2930 } 2931 2932 /* 2933 * Iterate over the process's address space mappings. 2934 */ 2935 int 2936 Pmapping_iter(struct ps_prochandle *P, proc_map_f *func, void *cd) 2937 { 2938 map_info_t *mptr; 2939 file_info_t *fptr; 2940 char *object_name; 2941 int rc = 0; 2942 int i; 2943 2944 /* create all the file_info_t's for all the mappings */ 2945 (void) Prd_agent(P); 2946 2947 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) { 2948 if ((fptr = mptr->map_file) == NULL) 2949 object_name = NULL; 2950 else 2951 object_name = fptr->file_lname; 2952 if ((rc = func(cd, &mptr->map_pmap, object_name)) != 0) 2953 return (rc); 2954 } 2955 return (0); 2956 } 2957 2958 /* 2959 * Iterate over the process's mapped objects. 2960 */ 2961 int 2962 Pobject_iter(struct ps_prochandle *P, proc_map_f *func, void *cd) 2963 { 2964 map_info_t *mptr; 2965 file_info_t *fptr; 2966 uint_t cnt; 2967 int rc = 0; 2968 2969 (void) Prd_agent(P); /* create file_info_t's for all the mappings */ 2970 Pupdate_maps(P); 2971 2972 for (cnt = P->num_files, fptr = list_next(&P->file_head); 2973 cnt; cnt--, fptr = list_next(fptr)) { 2974 2975 const char *lname = fptr->file_lname ? fptr->file_lname : ""; 2976 2977 if ((mptr = fptr->file_map) == NULL) 2978 continue; 2979 2980 if ((rc = func(cd, &mptr->map_pmap, lname)) != 0) 2981 return (rc); 2982 } 2983 return (0); 2984 } 2985 2986 /* 2987 * Given a virtual address, return the name of the underlying 2988 * mapped object (file), as provided by the dynamic linker. 2989 * Return NULL on failure (no underlying shared library). 2990 */ 2991 char * 2992 Pobjname(struct ps_prochandle *P, uintptr_t addr, 2993 char *buffer, size_t bufsize) 2994 { 2995 map_info_t *mptr; 2996 file_info_t *fptr; 2997 2998 /* create all the file_info_t's for all the mappings */ 2999 (void) Prd_agent(P); 3000 3001 if ((mptr = Paddr2mptr(P, addr)) != NULL && 3002 (fptr = mptr->map_file) != NULL && 3003 fptr->file_lname != NULL) { 3004 (void) strncpy(buffer, fptr->file_lname, bufsize); 3005 if (strlen(fptr->file_lname) >= bufsize) 3006 buffer[bufsize-1] = '\0'; 3007 return (buffer); 3008 } 3009 return (NULL); 3010 } 3011 3012 /* 3013 * Given a virtual address, return the link map id of the underlying mapped 3014 * object (file), as provided by the dynamic linker. Return -1 on failure. 3015 */ 3016 int 3017 Plmid(struct ps_prochandle *P, uintptr_t addr, Lmid_t *lmidp) 3018 { 3019 map_info_t *mptr; 3020 file_info_t *fptr; 3021 3022 /* create all the file_info_t's for all the mappings */ 3023 (void) Prd_agent(P); 3024 3025 if ((mptr = Paddr2mptr(P, addr)) != NULL && 3026 (fptr = mptr->map_file) != NULL && fptr->file_lo != NULL) { 3027 *lmidp = fptr->file_lo->rl_lmident; 3028 return (0); 3029 } 3030 3031 return (-1); 3032 } 3033 3034 /* 3035 * Given an object name and optional lmid, iterate over the object's symbols. 3036 * If which == PR_SYMTAB, search the normal symbol table. 3037 * If which == PR_DYNSYM, search the dynamic symbol table. 3038 */ 3039 static int 3040 Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name, 3041 int which, int mask, pr_order_t order, proc_xsym_f *func, void *cd) 3042 { 3043 GElf_Sym sym; 3044 map_info_t *mptr; 3045 file_info_t *fptr; 3046 sym_tbl_t *symtab; 3047 Elf_Data *data; 3048 size_t symn; 3049 const char *strs; 3050 size_t strsz; 3051 prsyminfo_t si; 3052 int rv; 3053 uint_t *map, i, count, ndx; 3054 3055 if ((mptr = object_name_to_map(P, lmid, object_name)) == NULL) 3056 return (-1); 3057 3058 if ((fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */ 3059 fptr->file_elf == NULL) /* not an ELF file */ 3060 return (-1); 3061 3062 /* 3063 * Search the specified symbol table. 3064 */ 3065 switch (which) { 3066 case PR_SYMTAB: 3067 symtab = &fptr->file_symtab; 3068 si.prs_table = PR_SYMTAB; 3069 break; 3070 case PR_DYNSYM: 3071 symtab = &fptr->file_dynsym; 3072 si.prs_table = PR_DYNSYM; 3073 break; 3074 default: 3075 return (-1); 3076 } 3077 3078 si.prs_object = object_name; 3079 si.prs_lmid = fptr->file_lo == NULL ? 3080 LM_ID_BASE : fptr->file_lo->rl_lmident; 3081 3082 data = symtab->sym_data; 3083 symn = symtab->sym_symn; 3084 strs = symtab->sym_strs; 3085 strsz = symtab->sym_strsz; 3086 3087 if (data == NULL || strs == NULL) 3088 return (-1); 3089 3090 switch (order) { 3091 case PRO_NATURAL: 3092 map = NULL; 3093 count = symn; 3094 break; 3095 case PRO_BYNAME: 3096 map = symtab->sym_byname; 3097 count = symtab->sym_count; 3098 break; 3099 case PRO_BYADDR: 3100 map = symtab->sym_byaddr; 3101 count = symtab->sym_count; 3102 break; 3103 default: 3104 return (-1); 3105 } 3106 3107 rv = 0; 3108 3109 for (i = 0; i < count; i++) { 3110 ndx = map == NULL ? i : map[i]; 3111 if (gelf_getsym(data, ndx, &sym) != NULL) { 3112 uint_t s_bind, s_type, type; 3113 3114 if (sym.st_name >= strsz) /* invalid st_name */ 3115 continue; 3116 3117 s_bind = GELF_ST_BIND(sym.st_info); 3118 s_type = GELF_ST_TYPE(sym.st_info); 3119 3120 /* 3121 * In case you haven't already guessed, this relies on 3122 * the bitmask used in <libproc.h> for encoding symbol 3123 * type and binding matching the order of STB and STT 3124 * constants in <sys/elf.h>. ELF can't change without 3125 * breaking binary compatibility, so I think this is 3126 * reasonably fair game. 3127 */ 3128 if (s_bind < STB_NUM && s_type < STT_NUM) { 3129 type = (1 << (s_type + 8)) | (1 << s_bind); 3130 if ((type & ~mask) != 0) 3131 continue; 3132 } else 3133 continue; /* Invalid type or binding */ 3134 3135 if (GELF_ST_TYPE(sym.st_info) != STT_TLS) 3136 sym.st_value += fptr->file_dyn_base; 3137 3138 si.prs_name = strs + sym.st_name; 3139 si.prs_id = ndx; 3140 if ((rv = func(cd, &sym, strs + sym.st_name, &si)) != 0) 3141 break; 3142 } 3143 } 3144 3145 return (rv); 3146 } 3147 3148 int 3149 Pxsymbol_iter(struct ps_prochandle *P, Lmid_t lmid, const char *object_name, 3150 int which, int mask, proc_xsym_f *func, void *cd) 3151 { 3152 return (Psymbol_iter_com(P, lmid, object_name, which, mask, 3153 PRO_NATURAL, func, cd)); 3154 } 3155 3156 int 3157 Psymbol_iter_by_lmid(struct ps_prochandle *P, Lmid_t lmid, 3158 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3159 { 3160 return (Psymbol_iter_com(P, lmid, object_name, which, mask, 3161 PRO_NATURAL, (proc_xsym_f *)func, cd)); 3162 } 3163 3164 int 3165 Psymbol_iter(struct ps_prochandle *P, 3166 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3167 { 3168 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3169 PRO_NATURAL, (proc_xsym_f *)func, cd)); 3170 } 3171 3172 int 3173 Psymbol_iter_by_addr(struct ps_prochandle *P, 3174 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3175 { 3176 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3177 PRO_BYADDR, (proc_xsym_f *)func, cd)); 3178 } 3179 3180 int 3181 Psymbol_iter_by_name(struct ps_prochandle *P, 3182 const char *object_name, int which, int mask, proc_sym_f *func, void *cd) 3183 { 3184 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask, 3185 PRO_BYNAME, (proc_xsym_f *)func, cd)); 3186 } 3187 3188 /* 3189 * Get the platform string from the core file if we have it; 3190 * just perform the system call for the caller if this is a live process. 3191 */ 3192 char * 3193 Pplatform(struct ps_prochandle *P, char *s, size_t n) 3194 { 3195 if (P->state == PS_IDLE) { 3196 errno = ENODATA; 3197 return (NULL); 3198 } 3199 3200 if (P->state == PS_DEAD) { 3201 if (P->core->core_platform == NULL) { 3202 errno = ENODATA; 3203 return (NULL); 3204 } 3205 (void) strncpy(s, P->core->core_platform, n - 1); 3206 s[n - 1] = '\0'; 3207 3208 } else if (sysinfo(SI_PLATFORM, s, n) == -1) 3209 return (NULL); 3210 3211 return (s); 3212 } 3213 3214 /* 3215 * Get the uname(2) information from the core file if we have it; 3216 * just perform the system call for the caller if this is a live process. 3217 */ 3218 int 3219 Puname(struct ps_prochandle *P, struct utsname *u) 3220 { 3221 if (P->state == PS_IDLE) { 3222 errno = ENODATA; 3223 return (-1); 3224 } 3225 3226 if (P->state == PS_DEAD) { 3227 if (P->core->core_uts == NULL) { 3228 errno = ENODATA; 3229 return (-1); 3230 } 3231 (void) memcpy(u, P->core->core_uts, sizeof (struct utsname)); 3232 return (0); 3233 } 3234 return (uname(u)); 3235 } 3236 3237 /* 3238 * Get the zone name from the core file if we have it; look up the 3239 * name based on the zone id if this is a live process. 3240 */ 3241 char * 3242 Pzonename(struct ps_prochandle *P, char *s, size_t n) 3243 { 3244 if (P->state == PS_IDLE) { 3245 errno = ENODATA; 3246 return (NULL); 3247 } 3248 3249 if (P->state == PS_DEAD) { 3250 if (P->core->core_zonename == NULL) { 3251 errno = ENODATA; 3252 return (NULL); 3253 } 3254 (void) strlcpy(s, P->core->core_zonename, n); 3255 } else { 3256 if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0) 3257 return (NULL); 3258 s[n - 1] = '\0'; 3259 } 3260 return (s); 3261 } 3262 3263 /* 3264 * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize 3265 * the symbol table heads in the new ps_prochandle. 3266 */ 3267 void 3268 Pinitsym(struct ps_prochandle *P) 3269 { 3270 P->num_files = 0; 3271 list_link(&P->file_head, NULL); 3272 } 3273 3274 /* 3275 * Called from Prelease() to destroy the symbol tables. 3276 * Must be called by the client after an exec() in the victim process. 3277 */ 3278 void 3279 Preset_maps(struct ps_prochandle *P) 3280 { 3281 int i; 3282 3283 if (P->rap != NULL) { 3284 rd_delete(P->rap); 3285 P->rap = NULL; 3286 } 3287 3288 if (P->execname != NULL) { 3289 free(P->execname); 3290 P->execname = NULL; 3291 } 3292 3293 if (P->auxv != NULL) { 3294 free(P->auxv); 3295 P->auxv = NULL; 3296 P->nauxv = 0; 3297 } 3298 3299 for (i = 0; i < P->map_count; i++) 3300 map_info_free(P, &P->mappings[i]); 3301 3302 if (P->mappings != NULL) { 3303 free(P->mappings); 3304 P->mappings = NULL; 3305 } 3306 P->map_count = P->map_alloc = 0; 3307 3308 P->info_valid = 0; 3309 } 3310 3311 typedef struct getenv_data { 3312 char *buf; 3313 size_t bufsize; 3314 const char *search; 3315 size_t searchlen; 3316 } getenv_data_t; 3317 3318 /*ARGSUSED*/ 3319 static int 3320 getenv_func(void *data, struct ps_prochandle *P, uintptr_t addr, 3321 const char *nameval) 3322 { 3323 getenv_data_t *d = data; 3324 size_t len; 3325 3326 if (nameval == NULL) 3327 return (0); 3328 3329 if (d->searchlen < strlen(nameval) && 3330 strncmp(nameval, d->search, d->searchlen) == 0 && 3331 nameval[d->searchlen] == '=') { 3332 len = MIN(strlen(nameval), d->bufsize - 1); 3333 (void) strncpy(d->buf, nameval, len); 3334 d->buf[len] = '\0'; 3335 return (1); 3336 } 3337 3338 return (0); 3339 } 3340 3341 char * 3342 Pgetenv(struct ps_prochandle *P, const char *name, char *buf, size_t buflen) 3343 { 3344 getenv_data_t d; 3345 3346 d.buf = buf; 3347 d.bufsize = buflen; 3348 d.search = name; 3349 d.searchlen = strlen(name); 3350 3351 if (Penv_iter(P, getenv_func, &d) == 1) { 3352 char *equals = strchr(d.buf, '='); 3353 3354 if (equals != NULL) { 3355 (void) memmove(d.buf, equals + 1, 3356 d.buf + buflen - equals - 1); 3357 d.buf[d.buf + buflen - equals] = '\0'; 3358 3359 return (buf); 3360 } 3361 } 3362 3363 return (NULL); 3364 } 3365 3366 /* number of argument or environment pointers to read all at once */ 3367 #define NARG 100 3368 3369 int 3370 Penv_iter(struct ps_prochandle *P, proc_env_f *func, void *data) 3371 { 3372 const psinfo_t *psp; 3373 uintptr_t envpoff; 3374 GElf_Sym sym; 3375 int ret; 3376 char *buf, *nameval; 3377 size_t buflen; 3378 3379 int nenv = NARG; 3380 long envp[NARG]; 3381 3382 /* 3383 * Attempt to find the "_environ" variable in the process. 3384 * Failing that, use the original value provided by Ppsinfo(). 3385 */ 3386 if ((psp = Ppsinfo(P)) == NULL) 3387 return (-1); 3388 3389 envpoff = psp->pr_envp; /* Default if no _environ found */ 3390 3391 if (Plookup_by_name(P, PR_OBJ_EXEC, "_environ", &sym) == 0) { 3392 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 3393 if (Pread(P, &envpoff, sizeof (envpoff), 3394 sym.st_value) != sizeof (envpoff)) 3395 envpoff = psp->pr_envp; 3396 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) { 3397 uint32_t envpoff32; 3398 3399 if (Pread(P, &envpoff32, sizeof (envpoff32), 3400 sym.st_value) != sizeof (envpoff32)) 3401 envpoff = psp->pr_envp; 3402 else 3403 envpoff = envpoff32; 3404 } 3405 } 3406 3407 buflen = 128; 3408 buf = malloc(buflen); 3409 3410 ret = 0; 3411 for (;;) { 3412 uintptr_t envoff; 3413 3414 if (nenv == NARG) { 3415 (void) memset(envp, 0, sizeof (envp)); 3416 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 3417 if (Pread(P, envp, 3418 sizeof (envp), envpoff) <= 0) { 3419 ret = -1; 3420 break; 3421 } 3422 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) { 3423 uint32_t e32[NARG]; 3424 int i; 3425 3426 (void) memset(e32, 0, sizeof (e32)); 3427 if (Pread(P, e32, sizeof (e32), envpoff) <= 0) { 3428 ret = -1; 3429 break; 3430 } 3431 for (i = 0; i < NARG; i++) 3432 envp[i] = e32[i]; 3433 } 3434 nenv = 0; 3435 } 3436 3437 if ((envoff = envp[nenv++]) == NULL) 3438 break; 3439 3440 /* 3441 * Attempt to read the string from the process. 3442 */ 3443 again: 3444 ret = Pread_string(P, buf, buflen, envoff); 3445 3446 if (ret <= 0) { 3447 nameval = NULL; 3448 } else if (ret == buflen - 1) { 3449 free(buf); 3450 /* 3451 * Bail if we have a corrupted environment 3452 */ 3453 if (buflen >= ARG_MAX) 3454 return (-1); 3455 buflen *= 2; 3456 buf = malloc(buflen); 3457 goto again; 3458 } else { 3459 nameval = buf; 3460 } 3461 3462 if ((ret = func(data, P, envoff, nameval)) != 0) 3463 break; 3464 3465 envpoff += (P->status.pr_dmodel == PR_MODEL_LP64)? 8 : 4; 3466 } 3467 3468 free(buf); 3469 3470 return (ret); 3471 } 3472