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