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