xref: /onnv-gate/usr/src/lib/libproc/common/Pcore.c (revision 10382:58b58f435bfe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52712Snn35248  * Common Development and Distribution License (the "License").
62712Snn35248  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
229900SAli.Bahrami@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/utsname.h>
280Sstevel@tonic-gate #include <sys/sysmacros.h>
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <alloca.h>
310Sstevel@tonic-gate #include <rtld_db.h>
320Sstevel@tonic-gate #include <libgen.h>
330Sstevel@tonic-gate #include <limits.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <unistd.h>
370Sstevel@tonic-gate #include <errno.h>
380Sstevel@tonic-gate #include <gelf.h>
390Sstevel@tonic-gate #include <stddef.h>
400Sstevel@tonic-gate 
417675SEdward.Pilatowicz@Sun.COM #include "libproc.h"
420Sstevel@tonic-gate #include "Pcontrol.h"
430Sstevel@tonic-gate #include "P32ton.h"
440Sstevel@tonic-gate #include "Putil.h"
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Pcore.c - Code to initialize a ps_prochandle from a core dump.  We
480Sstevel@tonic-gate  * allocate an additional structure to hold information from the core
490Sstevel@tonic-gate  * file, and attach this to the standard ps_prochandle in place of the
500Sstevel@tonic-gate  * ability to examine /proc/<pid>/ files.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  * Basic i/o function for reading and writing from the process address space
550Sstevel@tonic-gate  * stored in the core file and associated shared libraries.  We compute the
560Sstevel@tonic-gate  * appropriate fd and offsets, and let the provided prw function do the rest.
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate static ssize_t
core_rw(struct ps_prochandle * P,void * buf,size_t n,uintptr_t addr,ssize_t (* prw)(int,void *,size_t,off64_t))590Sstevel@tonic-gate core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
600Sstevel@tonic-gate     ssize_t (*prw)(int, void *, size_t, off64_t))
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 	ssize_t resid = n;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	while (resid != 0) {
650Sstevel@tonic-gate 		map_info_t *mp = Paddr2mptr(P, addr);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 		uintptr_t mapoff;
680Sstevel@tonic-gate 		ssize_t len;
690Sstevel@tonic-gate 		off64_t off;
700Sstevel@tonic-gate 		int fd;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 		if (mp == NULL)
730Sstevel@tonic-gate 			break;	/* No mapping for this address */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 		if (mp->map_pmap.pr_mflags & MA_RESERVED1) {
760Sstevel@tonic-gate 			if (mp->map_file == NULL || mp->map_file->file_fd < 0)
770Sstevel@tonic-gate 				break;	/* No file or file not open */
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 			fd = mp->map_file->file_fd;
800Sstevel@tonic-gate 		} else
810Sstevel@tonic-gate 			fd = P->asfd;
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 		mapoff = addr - mp->map_pmap.pr_vaddr;
840Sstevel@tonic-gate 		len = MIN(resid, mp->map_pmap.pr_size - mapoff);
850Sstevel@tonic-gate 		off = mp->map_offset + mapoff;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 		if ((len = prw(fd, buf, len, off)) <= 0)
880Sstevel@tonic-gate 			break;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 		resid -= len;
910Sstevel@tonic-gate 		addr += len;
920Sstevel@tonic-gate 		buf = (char *)buf + len;
930Sstevel@tonic-gate 	}
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	/*
960Sstevel@tonic-gate 	 * Important: Be consistent with the behavior of i/o on the as file:
970Sstevel@tonic-gate 	 * writing to an invalid address yields EIO; reading from an invalid
980Sstevel@tonic-gate 	 * address falls through to returning success and zero bytes.
990Sstevel@tonic-gate 	 */
1000Sstevel@tonic-gate 	if (resid == n && n != 0 && prw != pread64) {
1010Sstevel@tonic-gate 		errno = EIO;
1020Sstevel@tonic-gate 		return (-1);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	return (n - resid);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate static ssize_t
Pread_core(struct ps_prochandle * P,void * buf,size_t n,uintptr_t addr)1090Sstevel@tonic-gate Pread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate 	return (core_rw(P, buf, n, addr, pread64));
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate static ssize_t
Pwrite_core(struct ps_prochandle * P,const void * buf,size_t n,uintptr_t addr)1150Sstevel@tonic-gate Pwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	return (core_rw(P, (void *)buf, n, addr,
1180Sstevel@tonic-gate 	    (ssize_t (*)(int, void *, size_t, off64_t)) pwrite64));
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate static const ps_rwops_t P_core_ops = { Pread_core, Pwrite_core };
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate  * Return the lwp_info_t for the given lwpid.  If no such lwpid has been
1250Sstevel@tonic-gate  * encountered yet, allocate a new structure and return a pointer to it.
1260Sstevel@tonic-gate  * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
1270Sstevel@tonic-gate  */
1280Sstevel@tonic-gate static lwp_info_t *
lwpid2info(struct ps_prochandle * P,lwpid_t id)1290Sstevel@tonic-gate lwpid2info(struct ps_prochandle *P, lwpid_t id)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
1320Sstevel@tonic-gate 	lwp_info_t *next;
1330Sstevel@tonic-gate 	uint_t i;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
1360Sstevel@tonic-gate 		if (lwp->lwp_id == id) {
1370Sstevel@tonic-gate 			P->core->core_lwp = lwp;
1380Sstevel@tonic-gate 			return (lwp);
1390Sstevel@tonic-gate 		}
1400Sstevel@tonic-gate 		if (lwp->lwp_id < id) {
1410Sstevel@tonic-gate 			break;
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 	}
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	next = lwp;
1460Sstevel@tonic-gate 	if ((lwp = calloc(1, sizeof (lwp_info_t))) == NULL)
1470Sstevel@tonic-gate 		return (NULL);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	list_link(lwp, next);
1500Sstevel@tonic-gate 	lwp->lwp_id = id;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	P->core->core_lwp = lwp;
1530Sstevel@tonic-gate 	P->core->core_nlwp++;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	return (lwp);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
1590Sstevel@tonic-gate  * The core file itself contains a series of NOTE segments containing saved
1600Sstevel@tonic-gate  * structures from /proc at the time the process died.  For each note we
1610Sstevel@tonic-gate  * comprehend, we define a function to read it in from the core file,
1620Sstevel@tonic-gate  * convert it to our native data model if necessary, and store it inside
1630Sstevel@tonic-gate  * the ps_prochandle.  Each function is invoked by Pfgrab_core() with the
1640Sstevel@tonic-gate  * seek pointer on P->asfd positioned appropriately.  We populate a table
1650Sstevel@tonic-gate  * of pointers to these note functions below.
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static int
note_pstatus(struct ps_prochandle * P,size_t nbytes)1690Sstevel@tonic-gate note_pstatus(struct ps_prochandle *P, size_t nbytes)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate #ifdef _LP64
1720Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
1730Sstevel@tonic-gate 		pstatus32_t ps32;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 		if (nbytes < sizeof (pstatus32_t) ||
1760Sstevel@tonic-gate 		    read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
1770Sstevel@tonic-gate 			goto err;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 		pstatus_32_to_n(&ps32, &P->status);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	} else
1820Sstevel@tonic-gate #endif
1830Sstevel@tonic-gate 	if (nbytes < sizeof (pstatus_t) ||
1840Sstevel@tonic-gate 	    read(P->asfd, &P->status, sizeof (pstatus_t)) != sizeof (pstatus_t))
1850Sstevel@tonic-gate 		goto err;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	P->orig_status = P->status;
1880Sstevel@tonic-gate 	P->pid = P->status.pr_pid;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	return (0);
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate err:
1930Sstevel@tonic-gate 	dprintf("Pgrab_core: failed to read NT_PSTATUS\n");
1940Sstevel@tonic-gate 	return (-1);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate static int
note_lwpstatus(struct ps_prochandle * P,size_t nbytes)1980Sstevel@tonic-gate note_lwpstatus(struct ps_prochandle *P, size_t nbytes)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate 	lwp_info_t *lwp;
2010Sstevel@tonic-gate 	lwpstatus_t lps;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate #ifdef _LP64
2040Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
2050Sstevel@tonic-gate 		lwpstatus32_t l32;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 		if (nbytes < sizeof (lwpstatus32_t) ||
2080Sstevel@tonic-gate 		    read(P->asfd, &l32, sizeof (l32)) != sizeof (l32))
2090Sstevel@tonic-gate 			goto err;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 		lwpstatus_32_to_n(&l32, &lps);
2120Sstevel@tonic-gate 	} else
2130Sstevel@tonic-gate #endif
2140Sstevel@tonic-gate 	if (nbytes < sizeof (lwpstatus_t) ||
2150Sstevel@tonic-gate 	    read(P->asfd, &lps, sizeof (lps)) != sizeof (lps))
2160Sstevel@tonic-gate 		goto err;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	if ((lwp = lwpid2info(P, lps.pr_lwpid)) == NULL) {
2190Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n");
2200Sstevel@tonic-gate 		return (-1);
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	/*
2240Sstevel@tonic-gate 	 * Erase a useless and confusing artifact of the kernel implementation:
2250Sstevel@tonic-gate 	 * the lwps which did *not* create the core will show SIGKILL.  We can
2260Sstevel@tonic-gate 	 * be assured this is bogus because SIGKILL can't produce core files.
2270Sstevel@tonic-gate 	 */
2280Sstevel@tonic-gate 	if (lps.pr_cursig == SIGKILL)
2290Sstevel@tonic-gate 		lps.pr_cursig = 0;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	(void) memcpy(&lwp->lwp_status, &lps, sizeof (lps));
2320Sstevel@tonic-gate 	return (0);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate err:
2350Sstevel@tonic-gate 	dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n");
2360Sstevel@tonic-gate 	return (-1);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate static int
note_psinfo(struct ps_prochandle * P,size_t nbytes)2400Sstevel@tonic-gate note_psinfo(struct ps_prochandle *P, size_t nbytes)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate #ifdef _LP64
2430Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
2440Sstevel@tonic-gate 		psinfo32_t ps32;
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 		if (nbytes < sizeof (psinfo32_t) ||
2470Sstevel@tonic-gate 		    read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
2480Sstevel@tonic-gate 			goto err;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 		psinfo_32_to_n(&ps32, &P->psinfo);
2510Sstevel@tonic-gate 	} else
2520Sstevel@tonic-gate #endif
2530Sstevel@tonic-gate 	if (nbytes < sizeof (psinfo_t) ||
2540Sstevel@tonic-gate 	    read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t))
2550Sstevel@tonic-gate 		goto err;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	dprintf("pr_fname = <%s>\n", P->psinfo.pr_fname);
2580Sstevel@tonic-gate 	dprintf("pr_psargs = <%s>\n", P->psinfo.pr_psargs);
2590Sstevel@tonic-gate 	dprintf("pr_wstat = 0x%x\n", P->psinfo.pr_wstat);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	return (0);
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate err:
2640Sstevel@tonic-gate 	dprintf("Pgrab_core: failed to read NT_PSINFO\n");
2650Sstevel@tonic-gate 	return (-1);
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate static int
note_lwpsinfo(struct ps_prochandle * P,size_t nbytes)2690Sstevel@tonic-gate note_lwpsinfo(struct ps_prochandle *P, size_t nbytes)
2700Sstevel@tonic-gate {
2710Sstevel@tonic-gate 	lwp_info_t *lwp;
2720Sstevel@tonic-gate 	lwpsinfo_t lps;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate #ifdef _LP64
2750Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
2760Sstevel@tonic-gate 		lwpsinfo32_t l32;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 		if (nbytes < sizeof (lwpsinfo32_t) ||
2790Sstevel@tonic-gate 		    read(P->asfd, &l32, sizeof (l32)) != sizeof (l32))
2800Sstevel@tonic-gate 			goto err;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 		lwpsinfo_32_to_n(&l32, &lps);
2830Sstevel@tonic-gate 	} else
2840Sstevel@tonic-gate #endif
2850Sstevel@tonic-gate 	if (nbytes < sizeof (lwpsinfo_t) ||
2860Sstevel@tonic-gate 	    read(P->asfd, &lps, sizeof (lps)) != sizeof (lps))
2870Sstevel@tonic-gate 		goto err;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	if ((lwp = lwpid2info(P, lps.pr_lwpid)) == NULL) {
2900Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to add NT_LWPSINFO\n");
2910Sstevel@tonic-gate 		return (-1);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	(void) memcpy(&lwp->lwp_psinfo, &lps, sizeof (lps));
2950Sstevel@tonic-gate 	return (0);
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate err:
2980Sstevel@tonic-gate 	dprintf("Pgrab_core: failed to read NT_LWPSINFO\n");
2990Sstevel@tonic-gate 	return (-1);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate static int
note_platform(struct ps_prochandle * P,size_t nbytes)3030Sstevel@tonic-gate note_platform(struct ps_prochandle *P, size_t nbytes)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate 	char *plat;
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	if (P->core->core_platform != NULL)
3080Sstevel@tonic-gate 		return (0);	/* Already seen */
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if (nbytes != 0 && ((plat = malloc(nbytes + 1)) != NULL)) {
3110Sstevel@tonic-gate 		if (read(P->asfd, plat, nbytes) != nbytes) {
3120Sstevel@tonic-gate 			dprintf("Pgrab_core: failed to read NT_PLATFORM\n");
3130Sstevel@tonic-gate 			free(plat);
3140Sstevel@tonic-gate 			return (-1);
3150Sstevel@tonic-gate 		}
3160Sstevel@tonic-gate 		plat[nbytes - 1] = '\0';
3170Sstevel@tonic-gate 		P->core->core_platform = plat;
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	return (0);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate static int
note_utsname(struct ps_prochandle * P,size_t nbytes)3240Sstevel@tonic-gate note_utsname(struct ps_prochandle *P, size_t nbytes)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	size_t ubytes = sizeof (struct utsname);
3270Sstevel@tonic-gate 	struct utsname *utsp;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	if (P->core->core_uts != NULL || nbytes < ubytes)
3300Sstevel@tonic-gate 		return (0);	/* Already seen or bad size */
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	if ((utsp = malloc(ubytes)) == NULL)
3330Sstevel@tonic-gate 		return (-1);
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	if (read(P->asfd, utsp, ubytes) != ubytes) {
3360Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_UTSNAME\n");
3370Sstevel@tonic-gate 		free(utsp);
3380Sstevel@tonic-gate 		return (-1);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (_libproc_debug) {
3420Sstevel@tonic-gate 		dprintf("uts.sysname = \"%s\"\n", utsp->sysname);
3430Sstevel@tonic-gate 		dprintf("uts.nodename = \"%s\"\n", utsp->nodename);
3440Sstevel@tonic-gate 		dprintf("uts.release = \"%s\"\n", utsp->release);
3450Sstevel@tonic-gate 		dprintf("uts.version = \"%s\"\n", utsp->version);
3460Sstevel@tonic-gate 		dprintf("uts.machine = \"%s\"\n", utsp->machine);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	P->core->core_uts = utsp;
3500Sstevel@tonic-gate 	return (0);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate static int
note_content(struct ps_prochandle * P,size_t nbytes)3540Sstevel@tonic-gate note_content(struct ps_prochandle *P, size_t nbytes)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate 	core_content_t content;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if (sizeof (P->core->core_content) != nbytes)
3590Sstevel@tonic-gate 		return (-1);
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if (read(P->asfd, &content, sizeof (content)) != sizeof (content))
3620Sstevel@tonic-gate 		return (-1);
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	P->core->core_content = content;
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	dprintf("core content = %llx\n", content);
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	return (0);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate static int
note_cred(struct ps_prochandle * P,size_t nbytes)3720Sstevel@tonic-gate note_cred(struct ps_prochandle *P, size_t nbytes)
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate 	prcred_t *pcrp;
3750Sstevel@tonic-gate 	int ngroups;
3760Sstevel@tonic-gate 	const size_t min_size = sizeof (prcred_t) - sizeof (gid_t);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/*
3790Sstevel@tonic-gate 	 * We allow for prcred_t notes that are actually smaller than a
3800Sstevel@tonic-gate 	 * prcred_t since the last member isn't essential if there are
3810Sstevel@tonic-gate 	 * no group memberships. This allows for more flexibility when it
3820Sstevel@tonic-gate 	 * comes to slightly malformed -- but still valid -- notes.
3830Sstevel@tonic-gate 	 */
3840Sstevel@tonic-gate 	if (P->core->core_cred != NULL || nbytes < min_size)
3850Sstevel@tonic-gate 		return (0);	/* Already seen or bad size */
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	ngroups = (nbytes - min_size) / sizeof (gid_t);
3880Sstevel@tonic-gate 	nbytes = sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	if ((pcrp = malloc(nbytes)) == NULL)
3910Sstevel@tonic-gate 		return (-1);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	if (read(P->asfd, pcrp, nbytes) != nbytes) {
3940Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_PRCRED\n");
3950Sstevel@tonic-gate 		free(pcrp);
3960Sstevel@tonic-gate 		return (-1);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	if (pcrp->pr_ngroups > ngroups) {
4000Sstevel@tonic-gate 		dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
4010Sstevel@tonic-gate 		    pcrp->pr_ngroups, ngroups);
4020Sstevel@tonic-gate 		pcrp->pr_ngroups = ngroups;
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	P->core->core_cred = pcrp;
4060Sstevel@tonic-gate 	return (0);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
4100Sstevel@tonic-gate static int
note_ldt(struct ps_prochandle * P,size_t nbytes)4110Sstevel@tonic-gate note_ldt(struct ps_prochandle *P, size_t nbytes)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate 	struct ssd *pldt;
4140Sstevel@tonic-gate 	uint_t nldt;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	if (P->core->core_ldt != NULL || nbytes < sizeof (struct ssd))
4170Sstevel@tonic-gate 		return (0);	/* Already seen or bad size */
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	nldt = nbytes / sizeof (struct ssd);
4200Sstevel@tonic-gate 	nbytes = nldt * sizeof (struct ssd);
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	if ((pldt = malloc(nbytes)) == NULL)
4230Sstevel@tonic-gate 		return (-1);
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	if (read(P->asfd, pldt, nbytes) != nbytes) {
4260Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_LDT\n");
4270Sstevel@tonic-gate 		free(pldt);
4280Sstevel@tonic-gate 		return (-1);
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	P->core->core_ldt = pldt;
4320Sstevel@tonic-gate 	P->core->core_nldt = nldt;
4330Sstevel@tonic-gate 	return (0);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate #endif	/* __i386 */
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate static int
note_priv(struct ps_prochandle * P,size_t nbytes)4380Sstevel@tonic-gate note_priv(struct ps_prochandle *P, size_t nbytes)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate 	prpriv_t *pprvp;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	if (P->core->core_priv != NULL || nbytes < sizeof (prpriv_t))
4430Sstevel@tonic-gate 		return (0);	/* Already seen or bad size */
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	if ((pprvp = malloc(nbytes)) == NULL)
4460Sstevel@tonic-gate 		return (-1);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (read(P->asfd, pprvp, nbytes) != nbytes) {
4490Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_PRPRIV\n");
4500Sstevel@tonic-gate 		free(pprvp);
4510Sstevel@tonic-gate 		return (-1);
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	P->core->core_priv = pprvp;
4550Sstevel@tonic-gate 	P->core->core_priv_size = nbytes;
4560Sstevel@tonic-gate 	return (0);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate static int
note_priv_info(struct ps_prochandle * P,size_t nbytes)4600Sstevel@tonic-gate note_priv_info(struct ps_prochandle *P, size_t nbytes)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate 	extern void *__priv_parse_info();
4630Sstevel@tonic-gate 	priv_impl_info_t *ppii;
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	if (P->core->core_privinfo != NULL ||
4660Sstevel@tonic-gate 	    nbytes < sizeof (priv_impl_info_t))
4670Sstevel@tonic-gate 		return (0);	/* Already seen or bad size */
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	if ((ppii = malloc(nbytes)) == NULL)
4700Sstevel@tonic-gate 		return (-1);
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	if (read(P->asfd, ppii, nbytes) != nbytes ||
4730Sstevel@tonic-gate 	    PRIV_IMPL_INFO_SIZE(ppii) != nbytes) {
4740Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_PRPRIVINFO\n");
4750Sstevel@tonic-gate 		free(ppii);
4760Sstevel@tonic-gate 		return (-1);
4770Sstevel@tonic-gate 	}
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	P->core->core_privinfo = __priv_parse_info(ppii);
4800Sstevel@tonic-gate 	P->core->core_ppii = ppii;
4810Sstevel@tonic-gate 	return (0);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate static int
note_zonename(struct ps_prochandle * P,size_t nbytes)4850Sstevel@tonic-gate note_zonename(struct ps_prochandle *P, size_t nbytes)
4860Sstevel@tonic-gate {
4870Sstevel@tonic-gate 	char *zonename;
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	if (P->core->core_zonename != NULL)
4900Sstevel@tonic-gate 		return (0);	/* Already seen */
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	if (nbytes != 0) {
4930Sstevel@tonic-gate 		if ((zonename = malloc(nbytes)) == NULL)
4940Sstevel@tonic-gate 			return (-1);
4950Sstevel@tonic-gate 		if (read(P->asfd, zonename, nbytes) != nbytes) {
4960Sstevel@tonic-gate 			dprintf("Pgrab_core: failed to read NT_ZONENAME\n");
4970Sstevel@tonic-gate 			free(zonename);
4980Sstevel@tonic-gate 			return (-1);
4990Sstevel@tonic-gate 		}
5000Sstevel@tonic-gate 		zonename[nbytes - 1] = '\0';
5010Sstevel@tonic-gate 		P->core->core_zonename = zonename;
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	return (0);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate static int
note_auxv(struct ps_prochandle * P,size_t nbytes)5080Sstevel@tonic-gate note_auxv(struct ps_prochandle *P, size_t nbytes)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate 	size_t n, i;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate #ifdef _LP64
5130Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
5140Sstevel@tonic-gate 		auxv32_t *a32;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		n = nbytes / sizeof (auxv32_t);
5170Sstevel@tonic-gate 		nbytes = n * sizeof (auxv32_t);
5180Sstevel@tonic-gate 		a32 = alloca(nbytes);
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 		if (read(P->asfd, a32, nbytes) != nbytes) {
5210Sstevel@tonic-gate 			dprintf("Pgrab_core: failed to read NT_AUXV\n");
5220Sstevel@tonic-gate 			return (-1);
5230Sstevel@tonic-gate 		}
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 		if ((P->auxv = malloc(sizeof (auxv_t) * (n + 1))) == NULL)
5260Sstevel@tonic-gate 			return (-1);
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		for (i = 0; i < n; i++)
5290Sstevel@tonic-gate 			auxv_32_to_n(&a32[i], &P->auxv[i]);
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	} else {
5320Sstevel@tonic-gate #endif
5330Sstevel@tonic-gate 		n = nbytes / sizeof (auxv_t);
5340Sstevel@tonic-gate 		nbytes = n * sizeof (auxv_t);
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 		if ((P->auxv = malloc(nbytes + sizeof (auxv_t))) == NULL)
5370Sstevel@tonic-gate 			return (-1);
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 		if (read(P->asfd, P->auxv, nbytes) != nbytes) {
5400Sstevel@tonic-gate 			free(P->auxv);
5410Sstevel@tonic-gate 			P->auxv = NULL;
5420Sstevel@tonic-gate 			return (-1);
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate #ifdef _LP64
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate #endif
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if (_libproc_debug) {
5490Sstevel@tonic-gate 		for (i = 0; i < n; i++) {
5500Sstevel@tonic-gate 			dprintf("P->auxv[%lu] = ( %d, 0x%lx )\n", (ulong_t)i,
5510Sstevel@tonic-gate 			    P->auxv[i].a_type, P->auxv[i].a_un.a_val);
5520Sstevel@tonic-gate 		}
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	/*
5560Sstevel@tonic-gate 	 * Defensive coding for loops which depend upon the auxv array being
5570Sstevel@tonic-gate 	 * terminated by an AT_NULL element; in each case, we've allocated
5580Sstevel@tonic-gate 	 * P->auxv to have an additional element which we force to be AT_NULL.
5590Sstevel@tonic-gate 	 */
5600Sstevel@tonic-gate 	P->auxv[n].a_type = AT_NULL;
5610Sstevel@tonic-gate 	P->auxv[n].a_un.a_val = 0L;
5620Sstevel@tonic-gate 	P->nauxv = (int)n;
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	return (0);
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate #ifdef __sparc
5680Sstevel@tonic-gate static int
note_xreg(struct ps_prochandle * P,size_t nbytes)5690Sstevel@tonic-gate note_xreg(struct ps_prochandle *P, size_t nbytes)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate 	lwp_info_t *lwp = P->core->core_lwp;
5720Sstevel@tonic-gate 	size_t xbytes = sizeof (prxregset_t);
5730Sstevel@tonic-gate 	prxregset_t *xregs;
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	if (lwp == NULL || lwp->lwp_xregs != NULL || nbytes < xbytes)
5760Sstevel@tonic-gate 		return (0);	/* No lwp yet, already seen, or bad size */
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	if ((xregs = malloc(xbytes)) == NULL)
5790Sstevel@tonic-gate 		return (-1);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	if (read(P->asfd, xregs, xbytes) != xbytes) {
5820Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_PRXREG\n");
5830Sstevel@tonic-gate 		free(xregs);
5840Sstevel@tonic-gate 		return (-1);
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	lwp->lwp_xregs = xregs;
5880Sstevel@tonic-gate 	return (0);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate static int
note_gwindows(struct ps_prochandle * P,size_t nbytes)5920Sstevel@tonic-gate note_gwindows(struct ps_prochandle *P, size_t nbytes)
5930Sstevel@tonic-gate {
5940Sstevel@tonic-gate 	lwp_info_t *lwp = P->core->core_lwp;
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	if (lwp == NULL || lwp->lwp_gwins != NULL || nbytes == 0)
5970Sstevel@tonic-gate 		return (0);	/* No lwp yet or already seen or no data */
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if ((lwp->lwp_gwins = malloc(sizeof (gwindows_t))) == NULL)
6000Sstevel@tonic-gate 		return (-1);
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	/*
6030Sstevel@tonic-gate 	 * Since the amount of gwindows data varies with how many windows were
6040Sstevel@tonic-gate 	 * actually saved, we just read up to the minimum of the note size
6050Sstevel@tonic-gate 	 * and the size of the gwindows_t type.  It doesn't matter if the read
6060Sstevel@tonic-gate 	 * fails since we have to zero out gwindows first anyway.
6070Sstevel@tonic-gate 	 */
6080Sstevel@tonic-gate #ifdef _LP64
6090Sstevel@tonic-gate 	if (P->core->core_dmodel == PR_MODEL_ILP32) {
6100Sstevel@tonic-gate 		gwindows32_t g32;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 		(void) memset(&g32, 0, sizeof (g32));
6130Sstevel@tonic-gate 		(void) read(P->asfd, &g32, MIN(nbytes, sizeof (g32)));
6140Sstevel@tonic-gate 		gwindows_32_to_n(&g32, lwp->lwp_gwins);
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	} else {
6170Sstevel@tonic-gate #endif
6180Sstevel@tonic-gate 		(void) memset(lwp->lwp_gwins, 0, sizeof (gwindows_t));
6190Sstevel@tonic-gate 		(void) read(P->asfd, lwp->lwp_gwins,
6200Sstevel@tonic-gate 		    MIN(nbytes, sizeof (gwindows_t)));
6210Sstevel@tonic-gate #ifdef _LP64
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate #endif
6240Sstevel@tonic-gate 	return (0);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate #ifdef __sparcv9
6280Sstevel@tonic-gate static int
note_asrs(struct ps_prochandle * P,size_t nbytes)6290Sstevel@tonic-gate note_asrs(struct ps_prochandle *P, size_t nbytes)
6300Sstevel@tonic-gate {
6310Sstevel@tonic-gate 	lwp_info_t *lwp = P->core->core_lwp;
6320Sstevel@tonic-gate 	int64_t *asrs;
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	if (lwp == NULL || lwp->lwp_asrs != NULL || nbytes < sizeof (asrset_t))
6350Sstevel@tonic-gate 		return (0);	/* No lwp yet, already seen, or bad size */
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	if ((asrs = malloc(sizeof (asrset_t))) == NULL)
6380Sstevel@tonic-gate 		return (-1);
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	if (read(P->asfd, asrs, sizeof (asrset_t)) != sizeof (asrset_t)) {
6410Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to read NT_ASRS\n");
6420Sstevel@tonic-gate 		free(asrs);
6430Sstevel@tonic-gate 		return (-1);
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	lwp->lwp_asrs = asrs;
6470Sstevel@tonic-gate 	return (0);
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate #endif	/* __sparcv9 */
6500Sstevel@tonic-gate #endif	/* __sparc */
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate /*ARGSUSED*/
6530Sstevel@tonic-gate static int
note_notsup(struct ps_prochandle * P,size_t nbytes)6540Sstevel@tonic-gate note_notsup(struct ps_prochandle *P, size_t nbytes)
6550Sstevel@tonic-gate {
6560Sstevel@tonic-gate 	dprintf("skipping unsupported note type\n");
6570Sstevel@tonic-gate 	return (0);
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate /*
6610Sstevel@tonic-gate  * Populate a table of function pointers indexed by Note type with our
6620Sstevel@tonic-gate  * functions to process each type of core file note:
6630Sstevel@tonic-gate  */
6640Sstevel@tonic-gate static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
6650Sstevel@tonic-gate 	note_notsup,		/*  0	unassigned		*/
6660Sstevel@tonic-gate 	note_notsup,		/*  1	NT_PRSTATUS (old)	*/
6670Sstevel@tonic-gate 	note_notsup,		/*  2	NT_PRFPREG (old)	*/
6680Sstevel@tonic-gate 	note_notsup,		/*  3	NT_PRPSINFO (old)	*/
6690Sstevel@tonic-gate #ifdef __sparc
6700Sstevel@tonic-gate 	note_xreg,		/*  4	NT_PRXREG		*/
6710Sstevel@tonic-gate #else
6720Sstevel@tonic-gate 	note_notsup,		/*  4	NT_PRXREG		*/
6730Sstevel@tonic-gate #endif
6740Sstevel@tonic-gate 	note_platform,		/*  5	NT_PLATFORM		*/
6750Sstevel@tonic-gate 	note_auxv,		/*  6	NT_AUXV			*/
6760Sstevel@tonic-gate #ifdef __sparc
6770Sstevel@tonic-gate 	note_gwindows,		/*  7	NT_GWINDOWS		*/
6780Sstevel@tonic-gate #ifdef __sparcv9
6790Sstevel@tonic-gate 	note_asrs,		/*  8	NT_ASRS			*/
6800Sstevel@tonic-gate #else
6810Sstevel@tonic-gate 	note_notsup,		/*  8	NT_ASRS			*/
6820Sstevel@tonic-gate #endif
6830Sstevel@tonic-gate #else
6840Sstevel@tonic-gate 	note_notsup,		/*  7	NT_GWINDOWS		*/
6850Sstevel@tonic-gate 	note_notsup,		/*  8	NT_ASRS			*/
6860Sstevel@tonic-gate #endif
6870Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
6880Sstevel@tonic-gate 	note_ldt,		/*  9	NT_LDT			*/
6890Sstevel@tonic-gate #else
6900Sstevel@tonic-gate 	note_notsup,		/*  9	NT_LDT			*/
6910Sstevel@tonic-gate #endif
6920Sstevel@tonic-gate 	note_pstatus,		/* 10	NT_PSTATUS		*/
6930Sstevel@tonic-gate 	note_notsup,		/* 11	unassigned		*/
6940Sstevel@tonic-gate 	note_notsup,		/* 12	unassigned		*/
6950Sstevel@tonic-gate 	note_psinfo,		/* 13	NT_PSINFO		*/
6960Sstevel@tonic-gate 	note_cred,		/* 14	NT_PRCRED		*/
6970Sstevel@tonic-gate 	note_utsname,		/* 15	NT_UTSNAME		*/
6980Sstevel@tonic-gate 	note_lwpstatus,		/* 16	NT_LWPSTATUS		*/
6990Sstevel@tonic-gate 	note_lwpsinfo,		/* 17	NT_LWPSINFO		*/
7000Sstevel@tonic-gate 	note_priv,		/* 18	NT_PRPRIV		*/
7010Sstevel@tonic-gate 	note_priv_info,		/* 19	NT_PRPRIVINFO		*/
7020Sstevel@tonic-gate 	note_content,		/* 20	NT_CONTENT		*/
7030Sstevel@tonic-gate 	note_zonename,		/* 21	NT_ZONENAME		*/
7040Sstevel@tonic-gate };
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate /*
7070Sstevel@tonic-gate  * Add information on the address space mapping described by the given
7080Sstevel@tonic-gate  * PT_LOAD program header.  We fill in more information on the mapping later.
7090Sstevel@tonic-gate  */
7100Sstevel@tonic-gate static int
core_add_mapping(struct ps_prochandle * P,GElf_Phdr * php)7110Sstevel@tonic-gate core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate 	int err = 0;
7140Sstevel@tonic-gate 	prmap_t pmap;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
7170Sstevel@tonic-gate 	    (u_longlong_t)php->p_vaddr, (u_longlong_t)php->p_filesz,
7180Sstevel@tonic-gate 	    (u_longlong_t)php->p_memsz, (u_longlong_t)php->p_offset);
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 	pmap.pr_vaddr = (uintptr_t)php->p_vaddr;
7210Sstevel@tonic-gate 	pmap.pr_size = php->p_memsz;
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 	/*
7240Sstevel@tonic-gate 	 * If Pgcore() or elfcore() fail to write a mapping, they will set
7250Sstevel@tonic-gate 	 * PF_SUNW_FAILURE in the Phdr and try to stash away the errno for us.
7260Sstevel@tonic-gate 	 */
7270Sstevel@tonic-gate 	if (php->p_flags & PF_SUNW_FAILURE) {
7280Sstevel@tonic-gate 		(void) pread64(P->asfd, &err,
7290Sstevel@tonic-gate 		    sizeof (err), (off64_t)php->p_offset);
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 		Perror_printf(P, "core file data for mapping at %p not saved: "
7320Sstevel@tonic-gate 		    "%s\n", (void *)(uintptr_t)php->p_vaddr, strerror(err));
7330Sstevel@tonic-gate 		dprintf("core file data for mapping at %p not saved: %s\n",
7340Sstevel@tonic-gate 		    (void *)(uintptr_t)php->p_vaddr, strerror(err));
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	} else if (php->p_filesz != 0 && php->p_offset >= P->core->core_size) {
7370Sstevel@tonic-gate 		Perror_printf(P, "core file may be corrupt -- data for mapping "
7380Sstevel@tonic-gate 		    "at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
7390Sstevel@tonic-gate 		dprintf("core file may be corrupt -- data for mapping "
7400Sstevel@tonic-gate 		    "at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	/*
7440Sstevel@tonic-gate 	 * The mapping name and offset will hopefully be filled in
7450Sstevel@tonic-gate 	 * by the librtld_db agent.  Unfortunately, if it isn't a
7460Sstevel@tonic-gate 	 * shared library mapping, this information is gone forever.
7470Sstevel@tonic-gate 	 */
7480Sstevel@tonic-gate 	pmap.pr_mapname[0] = '\0';
7490Sstevel@tonic-gate 	pmap.pr_offset = 0;
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	pmap.pr_mflags = 0;
7520Sstevel@tonic-gate 	if (php->p_flags & PF_R)
7530Sstevel@tonic-gate 		pmap.pr_mflags |= MA_READ;
7540Sstevel@tonic-gate 	if (php->p_flags & PF_W)
7550Sstevel@tonic-gate 		pmap.pr_mflags |= MA_WRITE;
7560Sstevel@tonic-gate 	if (php->p_flags & PF_X)
7570Sstevel@tonic-gate 		pmap.pr_mflags |= MA_EXEC;
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	if (php->p_filesz == 0)
7600Sstevel@tonic-gate 		pmap.pr_mflags |= MA_RESERVED1;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	/*
7630Sstevel@tonic-gate 	 * At the time of adding this mapping, we just zero the pagesize.
7640Sstevel@tonic-gate 	 * Once we've processed more of the core file, we'll have the
7650Sstevel@tonic-gate 	 * pagesize from the auxv's AT_PAGESZ element and we can fill this in.
7660Sstevel@tonic-gate 	 */
7670Sstevel@tonic-gate 	pmap.pr_pagesize = 0;
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 	/*
7700Sstevel@tonic-gate 	 * Unfortunately whether or not the mapping was a System V
7710Sstevel@tonic-gate 	 * shared memory segment is lost.  We use -1 to mark it as not shm.
7720Sstevel@tonic-gate 	 */
7730Sstevel@tonic-gate 	pmap.pr_shmid = -1;
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	return (Padd_mapping(P, php->p_offset, NULL, &pmap));
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate /*
7790Sstevel@tonic-gate  * Given a virtual address, name the mapping at that address using the
7800Sstevel@tonic-gate  * specified name, and return the map_info_t pointer.
7810Sstevel@tonic-gate  */
7820Sstevel@tonic-gate static map_info_t *
core_name_mapping(struct ps_prochandle * P,uintptr_t addr,const char * name)7830Sstevel@tonic-gate core_name_mapping(struct ps_prochandle *P, uintptr_t addr, const char *name)
7840Sstevel@tonic-gate {
7850Sstevel@tonic-gate 	map_info_t *mp = Paddr2mptr(P, addr);
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 	if (mp != NULL) {
7880Sstevel@tonic-gate 		(void) strncpy(mp->map_pmap.pr_mapname, name, PRMAPSZ);
7890Sstevel@tonic-gate 		mp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
7900Sstevel@tonic-gate 	}
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	return (mp);
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate /*
7960Sstevel@tonic-gate  * libproc uses libelf for all of its symbol table manipulation. This function
7970Sstevel@tonic-gate  * takes a symbol table and string table from a core file and places them
7980Sstevel@tonic-gate  * in a memory backed elf file.
7990Sstevel@tonic-gate  */
8000Sstevel@tonic-gate static void
fake_up_symtab(struct ps_prochandle * P,const elf_file_header_t * ehdr,GElf_Shdr * symtab,GElf_Shdr * strtab)801942Sahl fake_up_symtab(struct ps_prochandle *P, const elf_file_header_t *ehdr,
8020Sstevel@tonic-gate     GElf_Shdr *symtab, GElf_Shdr *strtab)
8030Sstevel@tonic-gate {
8040Sstevel@tonic-gate 	size_t size;
8050Sstevel@tonic-gate 	off64_t off, base;
8060Sstevel@tonic-gate 	map_info_t *mp;
8070Sstevel@tonic-gate 	file_info_t *fp;
8080Sstevel@tonic-gate 	Elf_Scn *scn;
8090Sstevel@tonic-gate 	Elf_Data *data;
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if (symtab->sh_addr == 0 ||
8120Sstevel@tonic-gate 	    (mp = Paddr2mptr(P, symtab->sh_addr)) == NULL ||
813*10201SEdward.Pilatowicz@Sun.COM 	    (fp = mp->map_file) == NULL) {
8142712Snn35248 		dprintf("fake_up_symtab: invalid section\n");
815*10201SEdward.Pilatowicz@Sun.COM 		return;
816*10201SEdward.Pilatowicz@Sun.COM 	}
817*10201SEdward.Pilatowicz@Sun.COM 
818*10201SEdward.Pilatowicz@Sun.COM 	if (fp->file_symtab.sym_data_pri != NULL) {
819*10201SEdward.Pilatowicz@Sun.COM 		dprintf("Symbol table already loaded (sh_addr 0x%lx)\n",
820*10201SEdward.Pilatowicz@Sun.COM 		    (long)symtab->sh_addr);
8210Sstevel@tonic-gate 		return;
8222712Snn35248 	}
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
8250Sstevel@tonic-gate 		struct {
8260Sstevel@tonic-gate 			Elf32_Ehdr ehdr;
8270Sstevel@tonic-gate 			Elf32_Shdr shdr[3];
8280Sstevel@tonic-gate 			char data[1];
8290Sstevel@tonic-gate 		} *b;
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 		base = sizeof (b->ehdr) + sizeof (b->shdr);
8320Sstevel@tonic-gate 		size = base + symtab->sh_size + strtab->sh_size;
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 		if ((b = calloc(1, size)) == NULL)
8350Sstevel@tonic-gate 			return;
8360Sstevel@tonic-gate 
837942Sahl 		(void) memcpy(b->ehdr.e_ident, ehdr->e_ident,
838942Sahl 		    sizeof (ehdr->e_ident));
839942Sahl 		b->ehdr.e_type = ehdr->e_type;
840942Sahl 		b->ehdr.e_machine = ehdr->e_machine;
841942Sahl 		b->ehdr.e_version = ehdr->e_version;
842942Sahl 		b->ehdr.e_flags = ehdr->e_flags;
8430Sstevel@tonic-gate 		b->ehdr.e_ehsize = sizeof (b->ehdr);
8440Sstevel@tonic-gate 		b->ehdr.e_shoff = sizeof (b->ehdr);
8450Sstevel@tonic-gate 		b->ehdr.e_shentsize = sizeof (b->shdr[0]);
8460Sstevel@tonic-gate 		b->ehdr.e_shnum = 3;
8470Sstevel@tonic-gate 		off = 0;
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 		b->shdr[1].sh_size = symtab->sh_size;
8500Sstevel@tonic-gate 		b->shdr[1].sh_type = SHT_SYMTAB;
8510Sstevel@tonic-gate 		b->shdr[1].sh_offset = off + base;
8520Sstevel@tonic-gate 		b->shdr[1].sh_entsize = sizeof (Elf32_Sym);
8530Sstevel@tonic-gate 		b->shdr[1].sh_link = 2;
8540Sstevel@tonic-gate 		b->shdr[1].sh_info =  symtab->sh_info;
8550Sstevel@tonic-gate 		b->shdr[1].sh_addralign = symtab->sh_addralign;
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 		if (pread64(P->asfd, &b->data[off], b->shdr[1].sh_size,
8580Sstevel@tonic-gate 		    symtab->sh_offset) != b->shdr[1].sh_size) {
8592712Snn35248 			dprintf("fake_up_symtab: pread of symtab[1] failed\n");
8600Sstevel@tonic-gate 			free(b);
8610Sstevel@tonic-gate 			return;
8620Sstevel@tonic-gate 		}
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 		off += b->shdr[1].sh_size;
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 		b->shdr[2].sh_flags = SHF_STRINGS;
8670Sstevel@tonic-gate 		b->shdr[2].sh_size = strtab->sh_size;
8680Sstevel@tonic-gate 		b->shdr[2].sh_type = SHT_STRTAB;
8690Sstevel@tonic-gate 		b->shdr[2].sh_offset = off + base;
8700Sstevel@tonic-gate 		b->shdr[2].sh_info =  strtab->sh_info;
8710Sstevel@tonic-gate 		b->shdr[2].sh_addralign = 1;
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 		if (pread64(P->asfd, &b->data[off], b->shdr[2].sh_size,
8740Sstevel@tonic-gate 		    strtab->sh_offset) != b->shdr[2].sh_size) {
8752712Snn35248 			dprintf("fake_up_symtab: pread of symtab[2] failed\n");
8760Sstevel@tonic-gate 			free(b);
8770Sstevel@tonic-gate 			return;
8780Sstevel@tonic-gate 		}
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 		off += b->shdr[2].sh_size;
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 		fp->file_symtab.sym_elf = elf_memory((char *)b, size);
8830Sstevel@tonic-gate 		if (fp->file_symtab.sym_elf == NULL) {
8840Sstevel@tonic-gate 			free(b);
8850Sstevel@tonic-gate 			return;
8860Sstevel@tonic-gate 		}
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 		fp->file_symtab.sym_elfmem = b;
8890Sstevel@tonic-gate #ifdef _LP64
8900Sstevel@tonic-gate 	} else {
8910Sstevel@tonic-gate 		struct {
8920Sstevel@tonic-gate 			Elf64_Ehdr ehdr;
8930Sstevel@tonic-gate 			Elf64_Shdr shdr[3];
8940Sstevel@tonic-gate 			char data[1];
8950Sstevel@tonic-gate 		} *b;
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 		base = sizeof (b->ehdr) + sizeof (b->shdr);
8980Sstevel@tonic-gate 		size = base + symtab->sh_size + strtab->sh_size;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 		if ((b = calloc(1, size)) == NULL)
9010Sstevel@tonic-gate 			return;
9020Sstevel@tonic-gate 
903942Sahl 		(void) memcpy(b->ehdr.e_ident, ehdr->e_ident,
904942Sahl 		    sizeof (ehdr->e_ident));
905942Sahl 		b->ehdr.e_type = ehdr->e_type;
906942Sahl 		b->ehdr.e_machine = ehdr->e_machine;
907942Sahl 		b->ehdr.e_version = ehdr->e_version;
908942Sahl 		b->ehdr.e_flags = ehdr->e_flags;
9090Sstevel@tonic-gate 		b->ehdr.e_ehsize = sizeof (b->ehdr);
9100Sstevel@tonic-gate 		b->ehdr.e_shoff = sizeof (b->ehdr);
9110Sstevel@tonic-gate 		b->ehdr.e_shentsize = sizeof (b->shdr[0]);
9120Sstevel@tonic-gate 		b->ehdr.e_shnum = 3;
9130Sstevel@tonic-gate 		off = 0;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 		b->shdr[1].sh_size = symtab->sh_size;
9160Sstevel@tonic-gate 		b->shdr[1].sh_type = SHT_SYMTAB;
9170Sstevel@tonic-gate 		b->shdr[1].sh_offset = off + base;
9180Sstevel@tonic-gate 		b->shdr[1].sh_entsize = sizeof (Elf64_Sym);
9190Sstevel@tonic-gate 		b->shdr[1].sh_link = 2;
9200Sstevel@tonic-gate 		b->shdr[1].sh_info =  symtab->sh_info;
9210Sstevel@tonic-gate 		b->shdr[1].sh_addralign = symtab->sh_addralign;
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 		if (pread64(P->asfd, &b->data[off], b->shdr[1].sh_size,
9240Sstevel@tonic-gate 		    symtab->sh_offset) != b->shdr[1].sh_size) {
9250Sstevel@tonic-gate 			free(b);
9260Sstevel@tonic-gate 			return;
9270Sstevel@tonic-gate 		}
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 		off += b->shdr[1].sh_size;
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 		b->shdr[2].sh_flags = SHF_STRINGS;
9320Sstevel@tonic-gate 		b->shdr[2].sh_size = strtab->sh_size;
9330Sstevel@tonic-gate 		b->shdr[2].sh_type = SHT_STRTAB;
9340Sstevel@tonic-gate 		b->shdr[2].sh_offset = off + base;
9350Sstevel@tonic-gate 		b->shdr[2].sh_info =  strtab->sh_info;
9360Sstevel@tonic-gate 		b->shdr[2].sh_addralign = 1;
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 		if (pread64(P->asfd, &b->data[off], b->shdr[2].sh_size,
9390Sstevel@tonic-gate 		    strtab->sh_offset) != b->shdr[2].sh_size) {
9400Sstevel@tonic-gate 			free(b);
9410Sstevel@tonic-gate 			return;
9420Sstevel@tonic-gate 		}
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 		off += b->shdr[2].sh_size;
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 		fp->file_symtab.sym_elf = elf_memory((char *)b, size);
9470Sstevel@tonic-gate 		if (fp->file_symtab.sym_elf == NULL) {
9480Sstevel@tonic-gate 			free(b);
9490Sstevel@tonic-gate 			return;
9500Sstevel@tonic-gate 		}
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 		fp->file_symtab.sym_elfmem = b;
9530Sstevel@tonic-gate #endif
9540Sstevel@tonic-gate 	}
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 	if ((scn = elf_getscn(fp->file_symtab.sym_elf, 1)) == NULL ||
9573347Sab196087 	    (fp->file_symtab.sym_data_pri = elf_getdata(scn, NULL)) == NULL ||
9580Sstevel@tonic-gate 	    (scn = elf_getscn(fp->file_symtab.sym_elf, 2)) == NULL ||
9592712Snn35248 	    (data = elf_getdata(scn, NULL)) == NULL) {
9602712Snn35248 		dprintf("fake_up_symtab: failed to get section data at %p\n",
9612712Snn35248 		    (void *)scn);
9620Sstevel@tonic-gate 		goto err;
9632712Snn35248 	}
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	fp->file_symtab.sym_strs = data->d_buf;
9660Sstevel@tonic-gate 	fp->file_symtab.sym_strsz = data->d_size;
9670Sstevel@tonic-gate 	fp->file_symtab.sym_symn = symtab->sh_size / symtab->sh_entsize;
9683347Sab196087 	fp->file_symtab.sym_hdr_pri = *symtab;
9690Sstevel@tonic-gate 	fp->file_symtab.sym_strhdr = *strtab;
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	optimize_symtab(&fp->file_symtab);
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 	return;
9740Sstevel@tonic-gate err:
9750Sstevel@tonic-gate 	(void) elf_end(fp->file_symtab.sym_elf);
9760Sstevel@tonic-gate 	free(fp->file_symtab.sym_elfmem);
9770Sstevel@tonic-gate 	fp->file_symtab.sym_elf = NULL;
9780Sstevel@tonic-gate 	fp->file_symtab.sym_elfmem = NULL;
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate static void
core_phdr_to_gelf(const Elf32_Phdr * src,GElf_Phdr * dst)9820Sstevel@tonic-gate core_phdr_to_gelf(const Elf32_Phdr *src, GElf_Phdr *dst)
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate 	dst->p_type = src->p_type;
9850Sstevel@tonic-gate 	dst->p_flags = src->p_flags;
9860Sstevel@tonic-gate 	dst->p_offset = (Elf64_Off)src->p_offset;
9870Sstevel@tonic-gate 	dst->p_vaddr = (Elf64_Addr)src->p_vaddr;
9880Sstevel@tonic-gate 	dst->p_paddr = (Elf64_Addr)src->p_paddr;
9890Sstevel@tonic-gate 	dst->p_filesz = (Elf64_Xword)src->p_filesz;
9900Sstevel@tonic-gate 	dst->p_memsz = (Elf64_Xword)src->p_memsz;
9910Sstevel@tonic-gate 	dst->p_align = (Elf64_Xword)src->p_align;
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate static void
core_shdr_to_gelf(const Elf32_Shdr * src,GElf_Shdr * dst)9950Sstevel@tonic-gate core_shdr_to_gelf(const Elf32_Shdr *src, GElf_Shdr *dst)
9960Sstevel@tonic-gate {
9970Sstevel@tonic-gate 	dst->sh_name = src->sh_name;
9980Sstevel@tonic-gate 	dst->sh_type = src->sh_type;
9990Sstevel@tonic-gate 	dst->sh_flags = (Elf64_Xword)src->sh_flags;
10000Sstevel@tonic-gate 	dst->sh_addr = (Elf64_Addr)src->sh_addr;
10010Sstevel@tonic-gate 	dst->sh_offset = (Elf64_Off)src->sh_offset;
10020Sstevel@tonic-gate 	dst->sh_size = (Elf64_Xword)src->sh_size;
10030Sstevel@tonic-gate 	dst->sh_link = src->sh_link;
10040Sstevel@tonic-gate 	dst->sh_info = src->sh_info;
10050Sstevel@tonic-gate 	dst->sh_addralign = (Elf64_Xword)src->sh_addralign;
10060Sstevel@tonic-gate 	dst->sh_entsize = (Elf64_Xword)src->sh_entsize;
10070Sstevel@tonic-gate }
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate /*
10100Sstevel@tonic-gate  * Perform elf_begin on efp->e_fd and verify the ELF file's type and class.
10110Sstevel@tonic-gate  */
10120Sstevel@tonic-gate static int
core_elf_fdopen(elf_file_t * efp,GElf_Half type,int * perr)10130Sstevel@tonic-gate core_elf_fdopen(elf_file_t *efp, GElf_Half type, int *perr)
10140Sstevel@tonic-gate {
10150Sstevel@tonic-gate #ifdef _BIG_ENDIAN
10160Sstevel@tonic-gate 	uchar_t order = ELFDATA2MSB;
10170Sstevel@tonic-gate #else
10180Sstevel@tonic-gate 	uchar_t order = ELFDATA2LSB;
10190Sstevel@tonic-gate #endif
10200Sstevel@tonic-gate 	Elf32_Ehdr e32;
10210Sstevel@tonic-gate 	int is_noelf = -1;
10220Sstevel@tonic-gate 	int isa_err = 0;
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 	/*
10250Sstevel@tonic-gate 	 * Because 32-bit libelf cannot deal with large files, we need to read,
10260Sstevel@tonic-gate 	 * check, and convert the file header manually in case type == ET_CORE.
10270Sstevel@tonic-gate 	 */
10280Sstevel@tonic-gate 	if (pread64(efp->e_fd, &e32, sizeof (e32), 0) != sizeof (e32)) {
10290Sstevel@tonic-gate 		if (perr != NULL)
10300Sstevel@tonic-gate 			*perr = G_FORMAT;
10310Sstevel@tonic-gate 		goto err;
10320Sstevel@tonic-gate 	}
10330Sstevel@tonic-gate 	if ((is_noelf = memcmp(&e32.e_ident[EI_MAG0], ELFMAG, SELFMAG)) != 0 ||
10340Sstevel@tonic-gate 	    e32.e_type != type || (isa_err = (e32.e_ident[EI_DATA] != order)) ||
10350Sstevel@tonic-gate 	    e32.e_version != EV_CURRENT) {
10360Sstevel@tonic-gate 		if (perr != NULL) {
10370Sstevel@tonic-gate 			if (is_noelf == 0 && isa_err) {
10380Sstevel@tonic-gate 				*perr = G_ISAINVAL;
10390Sstevel@tonic-gate 			} else {
10400Sstevel@tonic-gate 				*perr = G_FORMAT;
10410Sstevel@tonic-gate 			}
10420Sstevel@tonic-gate 		}
10430Sstevel@tonic-gate 		goto err;
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	/*
10470Sstevel@tonic-gate 	 * If the file is 64-bit and we are 32-bit, fail with G_LP64.  If the
1048942Sahl 	 * file is 64-bit and we are 64-bit, re-read the header as a Elf64_Ehdr,
1049942Sahl 	 * and convert it to a elf_file_header_t.  Otherwise, the file is
1050942Sahl 	 * 32-bit, so convert e32 to a elf_file_header_t.
10510Sstevel@tonic-gate 	 */
10520Sstevel@tonic-gate 	if (e32.e_ident[EI_CLASS] == ELFCLASS64) {
10530Sstevel@tonic-gate #ifdef _LP64
1054942Sahl 		Elf64_Ehdr e64;
1055942Sahl 
1056942Sahl 		if (pread64(efp->e_fd, &e64, sizeof (e64), 0) != sizeof (e64)) {
10570Sstevel@tonic-gate 			if (perr != NULL)
10580Sstevel@tonic-gate 				*perr = G_FORMAT;
10590Sstevel@tonic-gate 			goto err;
10600Sstevel@tonic-gate 		}
1061942Sahl 
1062942Sahl 		(void) memcpy(efp->e_hdr.e_ident, e64.e_ident, EI_NIDENT);
1063942Sahl 		efp->e_hdr.e_type = e64.e_type;
1064942Sahl 		efp->e_hdr.e_machine = e64.e_machine;
1065942Sahl 		efp->e_hdr.e_version = e64.e_version;
1066942Sahl 		efp->e_hdr.e_entry = e64.e_entry;
1067942Sahl 		efp->e_hdr.e_phoff = e64.e_phoff;
1068942Sahl 		efp->e_hdr.e_shoff = e64.e_shoff;
1069942Sahl 		efp->e_hdr.e_flags = e64.e_flags;
1070942Sahl 		efp->e_hdr.e_ehsize = e64.e_ehsize;
1071942Sahl 		efp->e_hdr.e_phentsize = e64.e_phentsize;
1072942Sahl 		efp->e_hdr.e_phnum = (Elf64_Word)e64.e_phnum;
1073942Sahl 		efp->e_hdr.e_shentsize = e64.e_shentsize;
1074942Sahl 		efp->e_hdr.e_shnum = (Elf64_Word)e64.e_shnum;
1075942Sahl 		efp->e_hdr.e_shstrndx = (Elf64_Word)e64.e_shstrndx;
10760Sstevel@tonic-gate #else	/* _LP64 */
10770Sstevel@tonic-gate 		if (perr != NULL)
10780Sstevel@tonic-gate 			*perr = G_LP64;
10790Sstevel@tonic-gate 		goto err;
10800Sstevel@tonic-gate #endif	/* _LP64 */
1081942Sahl 	} else {
1082942Sahl 		(void) memcpy(efp->e_hdr.e_ident, e32.e_ident, EI_NIDENT);
1083942Sahl 		efp->e_hdr.e_type = e32.e_type;
1084942Sahl 		efp->e_hdr.e_machine = e32.e_machine;
1085942Sahl 		efp->e_hdr.e_version = e32.e_version;
1086942Sahl 		efp->e_hdr.e_entry = (Elf64_Addr)e32.e_entry;
1087942Sahl 		efp->e_hdr.e_phoff = (Elf64_Off)e32.e_phoff;
1088942Sahl 		efp->e_hdr.e_shoff = (Elf64_Off)e32.e_shoff;
1089942Sahl 		efp->e_hdr.e_flags = e32.e_flags;
1090942Sahl 		efp->e_hdr.e_ehsize = e32.e_ehsize;
1091942Sahl 		efp->e_hdr.e_phentsize = e32.e_phentsize;
1092942Sahl 		efp->e_hdr.e_phnum = (Elf64_Word)e32.e_phnum;
1093942Sahl 		efp->e_hdr.e_shentsize = e32.e_shentsize;
1094942Sahl 		efp->e_hdr.e_shnum = (Elf64_Word)e32.e_shnum;
1095942Sahl 		efp->e_hdr.e_shstrndx = (Elf64_Word)e32.e_shstrndx;
1096942Sahl 	}
1097942Sahl 
1098942Sahl 	/*
1099942Sahl 	 * If the number of section headers or program headers or the section
1100942Sahl 	 * header string table index would overflow their respective fields
1101942Sahl 	 * in the ELF header, they're stored in the section header at index
1102942Sahl 	 * zero. To simplify use elsewhere, we look for those sentinel values
1103942Sahl 	 * here.
1104942Sahl 	 */
1105942Sahl 	if ((efp->e_hdr.e_shnum == 0 && efp->e_hdr.e_shoff != 0) ||
1106942Sahl 	    efp->e_hdr.e_shstrndx == SHN_XINDEX ||
1107942Sahl 	    efp->e_hdr.e_phnum == PN_XNUM) {
1108942Sahl 		GElf_Shdr shdr;
1109942Sahl 
1110942Sahl 		dprintf("extended ELF header\n");
1111942Sahl 
1112942Sahl 		if (efp->e_hdr.e_shoff == 0) {
1113942Sahl 			if (perr != NULL)
1114942Sahl 				*perr = G_FORMAT;
1115942Sahl 			goto err;
1116942Sahl 		}
1117942Sahl 
1118942Sahl 		if (efp->e_hdr.e_ident[EI_CLASS] == ELFCLASS32) {
1119942Sahl 			Elf32_Shdr shdr32;
1120942Sahl 
1121942Sahl 			if (pread64(efp->e_fd, &shdr32, sizeof (shdr32),
1122942Sahl 			    efp->e_hdr.e_shoff) != sizeof (shdr32)) {
1123942Sahl 				if (perr != NULL)
1124942Sahl 					*perr = G_FORMAT;
1125942Sahl 				goto err;
1126942Sahl 			}
1127942Sahl 
1128942Sahl 			core_shdr_to_gelf(&shdr32, &shdr);
1129942Sahl 		} else {
1130942Sahl 			if (pread64(efp->e_fd, &shdr, sizeof (shdr),
1131942Sahl 			    efp->e_hdr.e_shoff) != sizeof (shdr)) {
1132942Sahl 				if (perr != NULL)
1133942Sahl 					*perr = G_FORMAT;
1134942Sahl 				goto err;
1135942Sahl 			}
1136942Sahl 		}
1137942Sahl 
1138942Sahl 		if (efp->e_hdr.e_shnum == 0) {
1139942Sahl 			efp->e_hdr.e_shnum = shdr.sh_size;
1140942Sahl 			dprintf("section header count %lu\n",
1141942Sahl 			    (ulong_t)shdr.sh_size);
1142942Sahl 		}
1143942Sahl 
1144942Sahl 		if (efp->e_hdr.e_shstrndx == SHN_XINDEX) {
1145942Sahl 			efp->e_hdr.e_shstrndx = shdr.sh_link;
1146942Sahl 			dprintf("section string index %u\n", shdr.sh_link);
1147942Sahl 		}
1148942Sahl 
1149942Sahl 		if (efp->e_hdr.e_phnum == PN_XNUM && shdr.sh_info != 0) {
1150942Sahl 			efp->e_hdr.e_phnum = shdr.sh_info;
1151942Sahl 			dprintf("program header count %u\n", shdr.sh_info);
1152942Sahl 		}
1153942Sahl 
1154942Sahl 	} else if (efp->e_hdr.e_phoff != 0) {
1155942Sahl 		GElf_Phdr phdr;
1156942Sahl 		uint64_t phnum;
1157942Sahl 
1158942Sahl 		/*
1159942Sahl 		 * It's possible this core file came from a system that
1160942Sahl 		 * accidentally truncated the e_phnum field without correctly
1161942Sahl 		 * using the extended format in the section header at index
1162942Sahl 		 * zero. We try to detect and correct that specific type of
1163942Sahl 		 * corruption by using the knowledge that the core dump
1164942Sahl 		 * routines usually place the data referenced by the first
1165942Sahl 		 * program header immediately after the last header element.
1166942Sahl 		 */
1167942Sahl 		if (efp->e_hdr.e_ident[EI_CLASS] == ELFCLASS32) {
1168942Sahl 			Elf32_Phdr phdr32;
1169942Sahl 
1170942Sahl 			if (pread64(efp->e_fd, &phdr32, sizeof (phdr32),
1171942Sahl 			    efp->e_hdr.e_phoff) != sizeof (phdr32)) {
1172942Sahl 				if (perr != NULL)
1173942Sahl 					*perr = G_FORMAT;
1174942Sahl 				goto err;
1175942Sahl 			}
1176942Sahl 
1177942Sahl 			core_phdr_to_gelf(&phdr32, &phdr);
1178942Sahl 		} else {
1179942Sahl 			if (pread64(efp->e_fd, &phdr, sizeof (phdr),
1180942Sahl 			    efp->e_hdr.e_phoff) != sizeof (phdr)) {
1181942Sahl 				if (perr != NULL)
1182942Sahl 					*perr = G_FORMAT;
1183942Sahl 				goto err;
1184942Sahl 			}
1185942Sahl 		}
1186942Sahl 
1187942Sahl 		phnum = phdr.p_offset - efp->e_hdr.e_ehsize -
1188942Sahl 		    (uint64_t)efp->e_hdr.e_shnum * efp->e_hdr.e_shentsize;
1189942Sahl 		phnum /= efp->e_hdr.e_phentsize;
1190942Sahl 
1191942Sahl 		if (phdr.p_offset != 0 && phnum != efp->e_hdr.e_phnum) {
1192942Sahl 			dprintf("suspicious program header count %u %u\n",
1193942Sahl 			    (uint_t)phnum, efp->e_hdr.e_phnum);
1194942Sahl 
1195942Sahl 			/*
1196942Sahl 			 * If the new program header count we computed doesn't
1197942Sahl 			 * jive with count in the ELF header, we'll use the
1198942Sahl 			 * data that's there and hope for the best.
1199942Sahl 			 *
1200942Sahl 			 * If it does, it's also possible that the section
1201942Sahl 			 * header offset is incorrect; we'll check that and
1202942Sahl 			 * possibly try to fix it.
1203942Sahl 			 */
1204942Sahl 			if (phnum <= INT_MAX &&
1205942Sahl 			    (uint16_t)phnum == efp->e_hdr.e_phnum) {
1206942Sahl 
1207942Sahl 				if (efp->e_hdr.e_shoff == efp->e_hdr.e_phoff +
1208942Sahl 				    efp->e_hdr.e_phentsize *
1209942Sahl 				    (uint_t)efp->e_hdr.e_phnum) {
1210942Sahl 					efp->e_hdr.e_shoff =
1211942Sahl 					    efp->e_hdr.e_phoff +
1212942Sahl 					    efp->e_hdr.e_phentsize * phnum;
1213942Sahl 				}
1214942Sahl 
1215942Sahl 				efp->e_hdr.e_phnum = (Elf64_Word)phnum;
1216942Sahl 				dprintf("using new program header count\n");
1217942Sahl 			} else {
1218942Sahl 				dprintf("inconsistent program header count\n");
1219942Sahl 			}
1220942Sahl 		}
1221942Sahl 	}
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 	/*
12240Sstevel@tonic-gate 	 * The libelf implementation was never ported to be large-file aware.
12250Sstevel@tonic-gate 	 * This is typically not a problem for your average executable or
12260Sstevel@tonic-gate 	 * shared library, but a large 32-bit core file can exceed 2GB in size.
12270Sstevel@tonic-gate 	 * So if type is ET_CORE, we don't bother doing elf_begin; the code
12280Sstevel@tonic-gate 	 * in Pfgrab_core() below will do its own i/o and struct conversion.
12290Sstevel@tonic-gate 	 */
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	if (type == ET_CORE) {
12320Sstevel@tonic-gate 		efp->e_elf = NULL;
12330Sstevel@tonic-gate 		return (0);
12340Sstevel@tonic-gate 	}
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 	if ((efp->e_elf = elf_begin(efp->e_fd, ELF_C_READ, NULL)) == NULL) {
12370Sstevel@tonic-gate 		if (perr != NULL)
12380Sstevel@tonic-gate 			*perr = G_ELF;
12390Sstevel@tonic-gate 		goto err;
12400Sstevel@tonic-gate 	}
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate 	return (0);
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate err:
12450Sstevel@tonic-gate 	efp->e_elf = NULL;
12460Sstevel@tonic-gate 	return (-1);
12470Sstevel@tonic-gate }
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate /*
12500Sstevel@tonic-gate  * Open the specified file and then do a core_elf_fdopen on it.
12510Sstevel@tonic-gate  */
12520Sstevel@tonic-gate static int
core_elf_open(elf_file_t * efp,const char * path,GElf_Half type,int * perr)12530Sstevel@tonic-gate core_elf_open(elf_file_t *efp, const char *path, GElf_Half type, int *perr)
12540Sstevel@tonic-gate {
12550Sstevel@tonic-gate 	(void) memset(efp, 0, sizeof (elf_file_t));
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate 	if ((efp->e_fd = open64(path, O_RDONLY)) >= 0) {
12580Sstevel@tonic-gate 		if (core_elf_fdopen(efp, type, perr) == 0)
12590Sstevel@tonic-gate 			return (0);
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 		(void) close(efp->e_fd);
12620Sstevel@tonic-gate 		efp->e_fd = -1;
12630Sstevel@tonic-gate 	}
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	return (-1);
12660Sstevel@tonic-gate }
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate /*
12690Sstevel@tonic-gate  * Close the ELF handle and file descriptor.
12700Sstevel@tonic-gate  */
12710Sstevel@tonic-gate static void
core_elf_close(elf_file_t * efp)12720Sstevel@tonic-gate core_elf_close(elf_file_t *efp)
12730Sstevel@tonic-gate {
12740Sstevel@tonic-gate 	if (efp->e_elf != NULL) {
12750Sstevel@tonic-gate 		(void) elf_end(efp->e_elf);
12760Sstevel@tonic-gate 		efp->e_elf = NULL;
12770Sstevel@tonic-gate 	}
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	if (efp->e_fd != -1) {
12800Sstevel@tonic-gate 		(void) close(efp->e_fd);
12810Sstevel@tonic-gate 		efp->e_fd = -1;
12820Sstevel@tonic-gate 	}
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate /*
12860Sstevel@tonic-gate  * Given an ELF file for a statically linked executable, locate the likely
12870Sstevel@tonic-gate  * primary text section and fill in rl_base with its virtual address.
12880Sstevel@tonic-gate  */
12890Sstevel@tonic-gate static map_info_t *
core_find_text(struct ps_prochandle * P,Elf * elf,rd_loadobj_t * rlp)12900Sstevel@tonic-gate core_find_text(struct ps_prochandle *P, Elf *elf, rd_loadobj_t *rlp)
12910Sstevel@tonic-gate {
12920Sstevel@tonic-gate 	GElf_Phdr phdr;
12930Sstevel@tonic-gate 	uint_t i;
1294942Sahl 	size_t nphdrs;
12950Sstevel@tonic-gate 
12969900SAli.Bahrami@Sun.COM 	if (elf_getphdrnum(elf, &nphdrs) == -1)
1297942Sahl 		return (NULL);
1298942Sahl 
1299942Sahl 	for (i = 0; i < nphdrs; i++) {
1300942Sahl 		if (gelf_getphdr(elf, i, &phdr) != NULL &&
1301942Sahl 		    phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
1302942Sahl 			rlp->rl_base = phdr.p_vaddr;
1303942Sahl 			return (Paddr2mptr(P, rlp->rl_base));
13040Sstevel@tonic-gate 		}
13050Sstevel@tonic-gate 	}
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	return (NULL);
13080Sstevel@tonic-gate }
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate /*
13110Sstevel@tonic-gate  * Given an ELF file and the librtld_db structure corresponding to its primary
13120Sstevel@tonic-gate  * text mapping, deduce where its data segment was loaded and fill in
13130Sstevel@tonic-gate  * rl_data_base and prmap_t.pr_offset accordingly.
13140Sstevel@tonic-gate  */
13150Sstevel@tonic-gate static map_info_t *
core_find_data(struct ps_prochandle * P,Elf * elf,rd_loadobj_t * rlp)13160Sstevel@tonic-gate core_find_data(struct ps_prochandle *P, Elf *elf, rd_loadobj_t *rlp)
13170Sstevel@tonic-gate {
13180Sstevel@tonic-gate 	GElf_Ehdr ehdr;
13190Sstevel@tonic-gate 	GElf_Phdr phdr;
13200Sstevel@tonic-gate 	map_info_t *mp;
13210Sstevel@tonic-gate 	uint_t i, pagemask;
1322942Sahl 	size_t nphdrs;
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 	rlp->rl_data_base = NULL;
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 	/*
13270Sstevel@tonic-gate 	 * Find the first loadable, writeable Phdr and compute rl_data_base
13280Sstevel@tonic-gate 	 * as the virtual address at which is was loaded.
13290Sstevel@tonic-gate 	 */
1330942Sahl 	if (gelf_getehdr(elf, &ehdr) == NULL ||
13319900SAli.Bahrami@Sun.COM 	    elf_getphdrnum(elf, &nphdrs) == -1)
1332942Sahl 		return (NULL);
13330Sstevel@tonic-gate 
1334942Sahl 	for (i = 0; i < nphdrs; i++) {
1335942Sahl 		if (gelf_getphdr(elf, i, &phdr) != NULL &&
1336942Sahl 		    phdr.p_type == PT_LOAD && (phdr.p_flags & PF_W)) {
1337942Sahl 			rlp->rl_data_base = phdr.p_vaddr;
1338942Sahl 			if (ehdr.e_type == ET_DYN)
1339942Sahl 				rlp->rl_data_base += rlp->rl_base;
1340942Sahl 			break;
13410Sstevel@tonic-gate 		}
13420Sstevel@tonic-gate 	}
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	/*
13450Sstevel@tonic-gate 	 * If we didn't find an appropriate phdr or if the address we
13460Sstevel@tonic-gate 	 * computed has no mapping, return NULL.
13470Sstevel@tonic-gate 	 */
13480Sstevel@tonic-gate 	if (rlp->rl_data_base == NULL ||
13490Sstevel@tonic-gate 	    (mp = Paddr2mptr(P, rlp->rl_data_base)) == NULL)
13500Sstevel@tonic-gate 		return (NULL);
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	/*
13530Sstevel@tonic-gate 	 * It wouldn't be procfs-related code if we didn't make use of
13540Sstevel@tonic-gate 	 * unclean knowledge of segvn, even in userland ... the prmap_t's
13550Sstevel@tonic-gate 	 * pr_offset field will be the segvn offset from mmap(2)ing the
13560Sstevel@tonic-gate 	 * data section, which will be the file offset & PAGEMASK.
13570Sstevel@tonic-gate 	 */
13580Sstevel@tonic-gate 	pagemask = ~(mp->map_pmap.pr_pagesize - 1);
13590Sstevel@tonic-gate 	mp->map_pmap.pr_offset = phdr.p_offset & pagemask;
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	return (mp);
13620Sstevel@tonic-gate }
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate /*
13650Sstevel@tonic-gate  * Librtld_db agent callback for iterating over load object mappings.
13660Sstevel@tonic-gate  * For each load object, we allocate a new file_info_t, perform naming,
13670Sstevel@tonic-gate  * and attempt to construct a symbol table for the load object.
13680Sstevel@tonic-gate  */
13690Sstevel@tonic-gate static int
core_iter_mapping(const rd_loadobj_t * rlp,struct ps_prochandle * P)13700Sstevel@tonic-gate core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P)
13710Sstevel@tonic-gate {
13727675SEdward.Pilatowicz@Sun.COM 	char lname[PATH_MAX], buf[PATH_MAX];
13730Sstevel@tonic-gate 	file_info_t *fp;
13740Sstevel@tonic-gate 	map_info_t *mp;
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 	if (Pread_string(P, lname, PATH_MAX, (off_t)rlp->rl_nameaddr) <= 0) {
13770Sstevel@tonic-gate 		dprintf("failed to read name %p\n", (void *)rlp->rl_nameaddr);
13780Sstevel@tonic-gate 		return (1); /* Keep going; forget this if we can't get a name */
13790Sstevel@tonic-gate 	}
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 	dprintf("rd_loadobj name = \"%s\" rl_base = %p\n",
13820Sstevel@tonic-gate 	    lname, (void *)rlp->rl_base);
13830Sstevel@tonic-gate 
13840Sstevel@tonic-gate 	if ((mp = Paddr2mptr(P, rlp->rl_base)) == NULL) {
13850Sstevel@tonic-gate 		dprintf("no mapping for %p\n", (void *)rlp->rl_base);
13860Sstevel@tonic-gate 		return (1); /* No mapping; advance to next mapping */
13870Sstevel@tonic-gate 	}
13880Sstevel@tonic-gate 
13894753Srh87107 	/*
13904753Srh87107 	 * Create a new file_info_t for this mapping, and therefore for
13914753Srh87107 	 * this load object.
13924753Srh87107 	 *
13934753Srh87107 	 * If there's an ELF header at the beginning of this mapping,
13944753Srh87107 	 * file_info_new() will try to use its section headers to
13954753Srh87107 	 * identify any other mappings that belong to this load object.
13964753Srh87107 	 */
13974753Srh87107 	if ((fp = mp->map_file) == NULL &&
13984753Srh87107 	    (fp = file_info_new(P, mp)) == NULL) {
13994753Srh87107 		P->core->core_errno = errno;
14004753Srh87107 		dprintf("failed to malloc mapping data\n");
14014753Srh87107 		return (0); /* Abort */
14024753Srh87107 	}
14034753Srh87107 	fp->file_map = mp;
14040Sstevel@tonic-gate 
14054753Srh87107 	/* Create a local copy of the load object representation */
14067675SEdward.Pilatowicz@Sun.COM 	if ((fp->file_lo = calloc(1, sizeof (rd_loadobj_t))) == NULL) {
14070Sstevel@tonic-gate 		P->core->core_errno = errno;
14080Sstevel@tonic-gate 		dprintf("failed to malloc mapping data\n");
14090Sstevel@tonic-gate 		return (0); /* Abort */
14100Sstevel@tonic-gate 	}
14110Sstevel@tonic-gate 	*fp->file_lo = *rlp;
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 	if (lname[0] != '\0') {
14140Sstevel@tonic-gate 		/*
14157675SEdward.Pilatowicz@Sun.COM 		 * Naming dance part 1: if we got a name from librtld_db, then
14160Sstevel@tonic-gate 		 * copy this name to the prmap_t if it is unnamed.  If the
14170Sstevel@tonic-gate 		 * file_info_t is unnamed, name it after the lname.
14180Sstevel@tonic-gate 		 */
14190Sstevel@tonic-gate 		if (mp->map_pmap.pr_mapname[0] == '\0') {
14200Sstevel@tonic-gate 			(void) strncpy(mp->map_pmap.pr_mapname, lname, PRMAPSZ);
14210Sstevel@tonic-gate 			mp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
14220Sstevel@tonic-gate 		}
14230Sstevel@tonic-gate 
14240Sstevel@tonic-gate 		if (fp->file_lname == NULL)
14250Sstevel@tonic-gate 			fp->file_lname = strdup(lname);
14260Sstevel@tonic-gate 
14270Sstevel@tonic-gate 	} else if (fp->file_lname == NULL &&
14280Sstevel@tonic-gate 	    mp->map_pmap.pr_mapname[0] != '\0') {
14290Sstevel@tonic-gate 		/*
14307675SEdward.Pilatowicz@Sun.COM 		 * Naming dance part 2: if the mapping is named and the
14310Sstevel@tonic-gate 		 * file_info_t is not, name the file after the mapping.
14320Sstevel@tonic-gate 		 */
14330Sstevel@tonic-gate 		fp->file_lname = strdup(mp->map_pmap.pr_mapname);
14340Sstevel@tonic-gate 	}
14350Sstevel@tonic-gate 
14367675SEdward.Pilatowicz@Sun.COM 	if ((fp->file_rname == NULL) &&
14377675SEdward.Pilatowicz@Sun.COM 	    (Pfindmap(P, mp, buf, sizeof (buf)) != NULL))
14387675SEdward.Pilatowicz@Sun.COM 		fp->file_rname = strdup(buf);
14397675SEdward.Pilatowicz@Sun.COM 
14400Sstevel@tonic-gate 	if (fp->file_lname != NULL)
14410Sstevel@tonic-gate 		fp->file_lbase = basename(fp->file_lname);
14427675SEdward.Pilatowicz@Sun.COM 	if (fp->file_rname != NULL)
14437675SEdward.Pilatowicz@Sun.COM 		fp->file_rbase = basename(fp->file_rname);
14440Sstevel@tonic-gate 
14454753Srh87107 	/* Associate the file and the mapping. */
14464753Srh87107 	(void) strncpy(fp->file_pname, mp->map_pmap.pr_mapname, PRMAPSZ);
14474753Srh87107 	fp->file_pname[PRMAPSZ - 1] = '\0';
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	/*
14504753Srh87107 	 * If no section headers were available then we'll have to
14514753Srh87107 	 * identify this load object's other mappings with what we've
14524753Srh87107 	 * got: the start and end of the object's corresponding
14534753Srh87107 	 * address space.
14540Sstevel@tonic-gate 	 */
14554753Srh87107 	if (fp->file_saddrs == NULL) {
14564753Srh87107 		for (mp = fp->file_map + 1; mp < P->mappings + P->map_count &&
14574753Srh87107 		    mp->map_pmap.pr_vaddr < rlp->rl_bend; mp++) {
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 			if (mp->map_file == NULL) {
14604753Srh87107 				dprintf("core_iter_mapping %s: associating "
14614753Srh87107 				    "segment at %p\n",
14622712Snn35248 				    fp->file_pname,
14632712Snn35248 				    (void *)mp->map_pmap.pr_vaddr);
14640Sstevel@tonic-gate 				mp->map_file = fp;
14650Sstevel@tonic-gate 				fp->file_ref++;
14662712Snn35248 			} else {
14674753Srh87107 				dprintf("core_iter_mapping %s: segment at "
14684753Srh87107 				    "%p already associated with %s\n",
14694753Srh87107 				    fp->file_pname,
14702712Snn35248 				    (void *)mp->map_pmap.pr_vaddr,
14714753Srh87107 				    (mp == fp->file_map ? "this file" :
14724753Srh87107 				    mp->map_file->file_pname));
14730Sstevel@tonic-gate 			}
14744753Srh87107 		}
14754753Srh87107 	}
14760Sstevel@tonic-gate 
14774753Srh87107 	/* Ensure that all this file's mappings are named. */
14784753Srh87107 	for (mp = fp->file_map; mp < P->mappings + P->map_count &&
14794753Srh87107 	    mp->map_file == fp; mp++) {
14804753Srh87107 		if (mp->map_pmap.pr_mapname[0] == '\0' &&
14814753Srh87107 		    !(mp->map_pmap.pr_mflags & MA_BREAK)) {
14824753Srh87107 			(void) strncpy(mp->map_pmap.pr_mapname, fp->file_pname,
14834753Srh87107 			    PRMAPSZ);
14844753Srh87107 			mp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
14850Sstevel@tonic-gate 		}
14864753Srh87107 	}
14874753Srh87107 
14884753Srh87107 	/* Attempt to build a symbol table for this file. */
14894753Srh87107 	Pbuild_file_symtab(P, fp);
14904753Srh87107 	if (fp->file_elf == NULL)
14914753Srh87107 		dprintf("core_iter_mapping: no symtab for %s\n",
14924753Srh87107 		    fp->file_pname);
14934753Srh87107 
14944753Srh87107 	/* Locate the start of a data segment associated with this file. */
14954753Srh87107 	if ((mp = core_find_data(P, fp->file_elf, fp->file_lo)) != NULL) {
14964753Srh87107 		dprintf("found data for %s at %p (pr_offset 0x%llx)\n",
14974753Srh87107 		    fp->file_pname, (void *)fp->file_lo->rl_data_base,
14984753Srh87107 		    mp->map_pmap.pr_offset);
14992712Snn35248 	} else {
15002712Snn35248 		dprintf("core_iter_mapping: no data found for %s\n",
15012712Snn35248 		    fp->file_pname);
15020Sstevel@tonic-gate 	}
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 	return (1); /* Advance to next mapping */
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate /*
15080Sstevel@tonic-gate  * Callback function for Pfindexec().  In order to confirm a given pathname,
15097675SEdward.Pilatowicz@Sun.COM  * we verify that we can open it as an ELF file of type ET_EXEC or ET_DYN.
15100Sstevel@tonic-gate  */
15110Sstevel@tonic-gate static int
core_exec_open(const char * path,void * efp)15120Sstevel@tonic-gate core_exec_open(const char *path, void *efp)
15130Sstevel@tonic-gate {
15147675SEdward.Pilatowicz@Sun.COM 	if (core_elf_open(efp, path, ET_EXEC, NULL) == 0)
15157675SEdward.Pilatowicz@Sun.COM 		return (1);
15167675SEdward.Pilatowicz@Sun.COM 	if (core_elf_open(efp, path, ET_DYN, NULL) == 0)
15177675SEdward.Pilatowicz@Sun.COM 		return (1);
15187675SEdward.Pilatowicz@Sun.COM 	return (0);
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate /*
15220Sstevel@tonic-gate  * Attempt to load any section headers found in the core file.  If present,
15230Sstevel@tonic-gate  * this will refer to non-loadable data added to the core file by the kernel
15240Sstevel@tonic-gate  * based on coreadm(1M) settings, including CTF data and the symbol table.
15250Sstevel@tonic-gate  */
15260Sstevel@tonic-gate static void
core_load_shdrs(struct ps_prochandle * P,elf_file_t * efp)15270Sstevel@tonic-gate core_load_shdrs(struct ps_prochandle *P, elf_file_t *efp)
15280Sstevel@tonic-gate {
15290Sstevel@tonic-gate 	GElf_Shdr *shp, *shdrs = NULL;
15300Sstevel@tonic-gate 	char *shstrtab = NULL;
15310Sstevel@tonic-gate 	ulong_t shstrtabsz;
15320Sstevel@tonic-gate 	const char *name;
15330Sstevel@tonic-gate 	map_info_t *mp;
15340Sstevel@tonic-gate 
15350Sstevel@tonic-gate 	size_t nbytes;
15360Sstevel@tonic-gate 	void *buf;
15370Sstevel@tonic-gate 	int i;
15380Sstevel@tonic-gate 
15390Sstevel@tonic-gate 	if (efp->e_hdr.e_shstrndx >= efp->e_hdr.e_shnum) {
15400Sstevel@tonic-gate 		dprintf("corrupt shstrndx (%u) exceeds shnum (%u)\n",
1541942Sahl 		    efp->e_hdr.e_shstrndx, efp->e_hdr.e_shnum);
15420Sstevel@tonic-gate 		return;
15430Sstevel@tonic-gate 	}
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate 	/*
15460Sstevel@tonic-gate 	 * Read the section header table from the core file and then iterate
15470Sstevel@tonic-gate 	 * over the section headers, converting each to a GElf_Shdr.
15480Sstevel@tonic-gate 	 */
15492712Snn35248 	if ((shdrs = malloc(efp->e_hdr.e_shnum * sizeof (GElf_Shdr))) == NULL) {
15500Sstevel@tonic-gate 		dprintf("failed to malloc %u section headers: %s\n",
15510Sstevel@tonic-gate 		    (uint_t)efp->e_hdr.e_shnum, strerror(errno));
15522712Snn35248 		return;
15532712Snn35248 	}
15542712Snn35248 
15552712Snn35248 	nbytes = efp->e_hdr.e_shnum * efp->e_hdr.e_shentsize;
15562712Snn35248 	if ((buf = malloc(nbytes)) == NULL) {
15572712Snn35248 		dprintf("failed to malloc %d bytes: %s\n", (int)nbytes,
15582712Snn35248 		    strerror(errno));
15592712Snn35248 		free(shdrs);
15600Sstevel@tonic-gate 		goto out;
15610Sstevel@tonic-gate 	}
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 	if (pread64(efp->e_fd, buf, nbytes, efp->e_hdr.e_shoff) != nbytes) {
15640Sstevel@tonic-gate 		dprintf("failed to read section headers at off %lld: %s\n",
15650Sstevel@tonic-gate 		    (longlong_t)efp->e_hdr.e_shoff, strerror(errno));
15660Sstevel@tonic-gate 		free(buf);
15670Sstevel@tonic-gate 		goto out;
15680Sstevel@tonic-gate 	}
15690Sstevel@tonic-gate 
15700Sstevel@tonic-gate 	for (i = 0; i < efp->e_hdr.e_shnum; i++) {
15710Sstevel@tonic-gate 		void *p = (uchar_t *)buf + efp->e_hdr.e_shentsize * i;
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 		if (efp->e_hdr.e_ident[EI_CLASS] == ELFCLASS32)
15740Sstevel@tonic-gate 			core_shdr_to_gelf(p, &shdrs[i]);
15750Sstevel@tonic-gate 		else
15760Sstevel@tonic-gate 			(void) memcpy(&shdrs[i], p, sizeof (GElf_Shdr));
15770Sstevel@tonic-gate 	}
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	free(buf);
15800Sstevel@tonic-gate 	buf = NULL;
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 	/*
15830Sstevel@tonic-gate 	 * Read the .shstrtab section from the core file, terminating it with
15840Sstevel@tonic-gate 	 * an extra \0 so that a corrupt section will not cause us to die.
15850Sstevel@tonic-gate 	 */
15860Sstevel@tonic-gate 	shp = &shdrs[efp->e_hdr.e_shstrndx];
15870Sstevel@tonic-gate 	shstrtabsz = shp->sh_size;
15880Sstevel@tonic-gate 
15890Sstevel@tonic-gate 	if ((shstrtab = malloc(shstrtabsz + 1)) == NULL) {
15900Sstevel@tonic-gate 		dprintf("failed to allocate %lu bytes for shstrtab\n",
15910Sstevel@tonic-gate 		    (ulong_t)shstrtabsz);
15920Sstevel@tonic-gate 		goto out;
15930Sstevel@tonic-gate 	}
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate 	if (pread64(efp->e_fd, shstrtab, shstrtabsz,
15960Sstevel@tonic-gate 	    shp->sh_offset) != shstrtabsz) {
15970Sstevel@tonic-gate 		dprintf("failed to read %lu bytes of shstrs at off %lld: %s\n",
15980Sstevel@tonic-gate 		    shstrtabsz, (longlong_t)shp->sh_offset, strerror(errno));
15990Sstevel@tonic-gate 		goto out;
16000Sstevel@tonic-gate 	}
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	shstrtab[shstrtabsz] = '\0';
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate 	/*
16050Sstevel@tonic-gate 	 * Now iterate over each section in the section header table, locating
16060Sstevel@tonic-gate 	 * sections of interest and initializing more of the ps_prochandle.
16070Sstevel@tonic-gate 	 */
16080Sstevel@tonic-gate 	for (i = 0; i < efp->e_hdr.e_shnum; i++) {
16090Sstevel@tonic-gate 		shp = &shdrs[i];
16100Sstevel@tonic-gate 		name = shstrtab + shp->sh_name;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 		if (shp->sh_name >= shstrtabsz) {
16130Sstevel@tonic-gate 			dprintf("skipping section [%d]: corrupt sh_name\n", i);
16140Sstevel@tonic-gate 			continue;
16150Sstevel@tonic-gate 		}
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 		if (shp->sh_link >= efp->e_hdr.e_shnum) {
16180Sstevel@tonic-gate 			dprintf("skipping section [%d]: corrupt sh_link\n", i);
16190Sstevel@tonic-gate 			continue;
16200Sstevel@tonic-gate 		}
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 		dprintf("found section header %s (sh_addr 0x%llx)\n",
16230Sstevel@tonic-gate 		    name, (u_longlong_t)shp->sh_addr);
16240Sstevel@tonic-gate 
16250Sstevel@tonic-gate 		if (strcmp(name, ".SUNW_ctf") == 0) {
16260Sstevel@tonic-gate 			if ((mp = Paddr2mptr(P, shp->sh_addr)) == NULL) {
16270Sstevel@tonic-gate 				dprintf("no map at addr 0x%llx for %s [%d]\n",
16280Sstevel@tonic-gate 				    (u_longlong_t)shp->sh_addr, name, i);
16290Sstevel@tonic-gate 				continue;
16300Sstevel@tonic-gate 			}
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 			if (mp->map_file == NULL ||
16330Sstevel@tonic-gate 			    mp->map_file->file_ctf_buf != NULL) {
16340Sstevel@tonic-gate 				dprintf("no mapping file or duplicate buffer "
16350Sstevel@tonic-gate 				    "for %s [%d]\n", name, i);
16360Sstevel@tonic-gate 				continue;
16370Sstevel@tonic-gate 			}
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 			if ((buf = malloc(shp->sh_size)) == NULL ||
16400Sstevel@tonic-gate 			    pread64(efp->e_fd, buf, shp->sh_size,
16410Sstevel@tonic-gate 			    shp->sh_offset) != shp->sh_size) {
16420Sstevel@tonic-gate 				dprintf("skipping section %s [%d]: %s\n",
16430Sstevel@tonic-gate 				    name, i, strerror(errno));
16440Sstevel@tonic-gate 				free(buf);
16450Sstevel@tonic-gate 				continue;
16460Sstevel@tonic-gate 			}
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 			mp->map_file->file_ctf_size = shp->sh_size;
16490Sstevel@tonic-gate 			mp->map_file->file_ctf_buf = buf;
16500Sstevel@tonic-gate 
16510Sstevel@tonic-gate 			if (shdrs[shp->sh_link].sh_type == SHT_DYNSYM)
16520Sstevel@tonic-gate 				mp->map_file->file_ctf_dyn = 1;
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate 		} else if (strcmp(name, ".symtab") == 0) {
16550Sstevel@tonic-gate 			fake_up_symtab(P, &efp->e_hdr,
16560Sstevel@tonic-gate 			    shp, &shdrs[shp->sh_link]);
16570Sstevel@tonic-gate 		}
16580Sstevel@tonic-gate 	}
16590Sstevel@tonic-gate out:
16600Sstevel@tonic-gate 	free(shstrtab);
16610Sstevel@tonic-gate 	free(shdrs);
16620Sstevel@tonic-gate }
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate /*
16650Sstevel@tonic-gate  * Main engine for core file initialization: given an fd for the core file
16660Sstevel@tonic-gate  * and an optional pathname, construct the ps_prochandle.  The aout_path can
16670Sstevel@tonic-gate  * either be a suggested executable pathname, or a suggested directory to
16680Sstevel@tonic-gate  * use as a possible current working directory.
16690Sstevel@tonic-gate  */
16700Sstevel@tonic-gate struct ps_prochandle *
Pfgrab_core(int core_fd,const char * aout_path,int * perr)16710Sstevel@tonic-gate Pfgrab_core(int core_fd, const char *aout_path, int *perr)
16720Sstevel@tonic-gate {
16730Sstevel@tonic-gate 	struct ps_prochandle *P;
16740Sstevel@tonic-gate 	map_info_t *stk_mp, *brk_mp;
16750Sstevel@tonic-gate 	const char *execname;
16760Sstevel@tonic-gate 	char *interp;
16770Sstevel@tonic-gate 	int i, notes, pagesize;
16780Sstevel@tonic-gate 	uintptr_t addr, base_addr;
16790Sstevel@tonic-gate 	struct stat64 stbuf;
16800Sstevel@tonic-gate 	void *phbuf, *php;
16810Sstevel@tonic-gate 	size_t nbytes;
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 	elf_file_t aout;
16840Sstevel@tonic-gate 	elf_file_t core;
16850Sstevel@tonic-gate 
16860Sstevel@tonic-gate 	Elf_Scn *scn, *intp_scn = NULL;
16870Sstevel@tonic-gate 	Elf_Data *dp;
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate 	GElf_Phdr phdr, note_phdr;
16900Sstevel@tonic-gate 	GElf_Shdr shdr;
16910Sstevel@tonic-gate 	GElf_Xword nleft;
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
16940Sstevel@tonic-gate 		dprintf("libproc ELF version is more recent than libelf\n");
16950Sstevel@tonic-gate 		*perr = G_ELF;
16960Sstevel@tonic-gate 		return (NULL);
16970Sstevel@tonic-gate 	}
16980Sstevel@tonic-gate 
16990Sstevel@tonic-gate 	aout.e_elf = NULL;
17000Sstevel@tonic-gate 	aout.e_fd = -1;
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 	core.e_elf = NULL;
17030Sstevel@tonic-gate 	core.e_fd = core_fd;
17040Sstevel@tonic-gate 
17050Sstevel@tonic-gate 	/*
17060Sstevel@tonic-gate 	 * Allocate and initialize a ps_prochandle structure for the core.
17070Sstevel@tonic-gate 	 * There are several key pieces of initialization here:
17080Sstevel@tonic-gate 	 *
17090Sstevel@tonic-gate 	 * 1. The PS_DEAD state flag marks this prochandle as a core file.
17100Sstevel@tonic-gate 	 *    PS_DEAD also thus prevents all operations which require state
17110Sstevel@tonic-gate 	 *    to be PS_STOP from operating on this handle.
17120Sstevel@tonic-gate 	 *
17130Sstevel@tonic-gate 	 * 2. We keep the core file fd in P->asfd since the core file contains
17140Sstevel@tonic-gate 	 *    the remnants of the process address space.
17150Sstevel@tonic-gate 	 *
17160Sstevel@tonic-gate 	 * 3. We set the P->info_valid bit because all information about the
17170Sstevel@tonic-gate 	 *    core is determined by the end of this function; there is no need
17180Sstevel@tonic-gate 	 *    for proc_update_maps() to reload mappings at any later point.
17190Sstevel@tonic-gate 	 *
17200Sstevel@tonic-gate 	 * 4. The read/write ops vector uses our core_rw() function defined
17210Sstevel@tonic-gate 	 *    above to handle i/o requests.
17220Sstevel@tonic-gate 	 */
17230Sstevel@tonic-gate 	if ((P = malloc(sizeof (struct ps_prochandle))) == NULL) {
17240Sstevel@tonic-gate 		*perr = G_STRANGE;
17250Sstevel@tonic-gate 		return (NULL);
17260Sstevel@tonic-gate 	}
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	(void) memset(P, 0, sizeof (struct ps_prochandle));
17290Sstevel@tonic-gate 	(void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
17300Sstevel@tonic-gate 	P->state = PS_DEAD;
17310Sstevel@tonic-gate 	P->pid = (pid_t)-1;
17320Sstevel@tonic-gate 	P->asfd = core.e_fd;
17330Sstevel@tonic-gate 	P->ctlfd = -1;
17340Sstevel@tonic-gate 	P->statfd = -1;
17350Sstevel@tonic-gate 	P->agentctlfd = -1;
17360Sstevel@tonic-gate 	P->agentstatfd = -1;
17377675SEdward.Pilatowicz@Sun.COM 	P->zoneroot = NULL;
17380Sstevel@tonic-gate 	P->info_valid = 1;
17390Sstevel@tonic-gate 	P->ops = &P_core_ops;
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate 	Pinitsym(P);
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	/*
17440Sstevel@tonic-gate 	 * Fstat and open the core file and make sure it is a valid ELF core.
17450Sstevel@tonic-gate 	 */
17460Sstevel@tonic-gate 	if (fstat64(P->asfd, &stbuf) == -1) {
17470Sstevel@tonic-gate 		*perr = G_STRANGE;
17480Sstevel@tonic-gate 		goto err;
17490Sstevel@tonic-gate 	}
17500Sstevel@tonic-gate 
17510Sstevel@tonic-gate 	if (core_elf_fdopen(&core, ET_CORE, perr) == -1)
17520Sstevel@tonic-gate 		goto err;
17530Sstevel@tonic-gate 
17540Sstevel@tonic-gate 	/*
17550Sstevel@tonic-gate 	 * Allocate and initialize a core_info_t to hang off the ps_prochandle
17560Sstevel@tonic-gate 	 * structure.  We keep all core-specific information in this structure.
17570Sstevel@tonic-gate 	 */
17587675SEdward.Pilatowicz@Sun.COM 	if ((P->core = calloc(1, sizeof (core_info_t))) == NULL) {
17590Sstevel@tonic-gate 		*perr = G_STRANGE;
17600Sstevel@tonic-gate 		goto err;
17610Sstevel@tonic-gate 	}
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate 	list_link(&P->core->core_lwp_head, NULL);
17640Sstevel@tonic-gate 	P->core->core_size = stbuf.st_size;
17650Sstevel@tonic-gate 	/*
17660Sstevel@tonic-gate 	 * In the days before adjustable core file content, this was the
17670Sstevel@tonic-gate 	 * default core file content. For new core files, this value will
17680Sstevel@tonic-gate 	 * be overwritten by the NT_CONTENT note section.
17690Sstevel@tonic-gate 	 */
17700Sstevel@tonic-gate 	P->core->core_content = CC_CONTENT_STACK | CC_CONTENT_HEAP |
17710Sstevel@tonic-gate 	    CC_CONTENT_DATA | CC_CONTENT_RODATA | CC_CONTENT_ANON |
17720Sstevel@tonic-gate 	    CC_CONTENT_SHANON;
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 	switch (core.e_hdr.e_ident[EI_CLASS]) {
17750Sstevel@tonic-gate 	case ELFCLASS32:
17760Sstevel@tonic-gate 		P->core->core_dmodel = PR_MODEL_ILP32;
17770Sstevel@tonic-gate 		break;
17780Sstevel@tonic-gate 	case ELFCLASS64:
17790Sstevel@tonic-gate 		P->core->core_dmodel = PR_MODEL_LP64;
17800Sstevel@tonic-gate 		break;
17810Sstevel@tonic-gate 	default:
17820Sstevel@tonic-gate 		*perr = G_FORMAT;
17830Sstevel@tonic-gate 		goto err;
17840Sstevel@tonic-gate 	}
17850Sstevel@tonic-gate 
17860Sstevel@tonic-gate 	/*
17870Sstevel@tonic-gate 	 * Because the core file may be a large file, we can't use libelf to
17880Sstevel@tonic-gate 	 * read the Phdrs.  We use e_phnum and e_phentsize to simplify things.
17890Sstevel@tonic-gate 	 */
17900Sstevel@tonic-gate 	nbytes = core.e_hdr.e_phnum * core.e_hdr.e_phentsize;
17910Sstevel@tonic-gate 
17920Sstevel@tonic-gate 	if ((phbuf = malloc(nbytes)) == NULL) {
17930Sstevel@tonic-gate 		*perr = G_STRANGE;
17940Sstevel@tonic-gate 		goto err;
17950Sstevel@tonic-gate 	}
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate 	if (pread64(core_fd, phbuf, nbytes, core.e_hdr.e_phoff) != nbytes) {
17980Sstevel@tonic-gate 		*perr = G_STRANGE;
17990Sstevel@tonic-gate 		free(phbuf);
18000Sstevel@tonic-gate 		goto err;
18010Sstevel@tonic-gate 	}
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	/*
18040Sstevel@tonic-gate 	 * Iterate through the program headers in the core file.
18050Sstevel@tonic-gate 	 * We're interested in two types of Phdrs: PT_NOTE (which
18060Sstevel@tonic-gate 	 * contains a set of saved /proc structures), and PT_LOAD (which
18070Sstevel@tonic-gate 	 * represents a memory mapping from the process's address space).
18080Sstevel@tonic-gate 	 * In the case of PT_NOTE, we're interested in the last PT_NOTE
18090Sstevel@tonic-gate 	 * in the core file; currently the first PT_NOTE (if present)
18100Sstevel@tonic-gate 	 * contains /proc structs in the pre-2.6 unstructured /proc format.
18110Sstevel@tonic-gate 	 */
18120Sstevel@tonic-gate 	for (php = phbuf, notes = 0, i = 0; i < core.e_hdr.e_phnum; i++) {
18130Sstevel@tonic-gate 		if (core.e_hdr.e_ident[EI_CLASS] == ELFCLASS64)
18140Sstevel@tonic-gate 			(void) memcpy(&phdr, php, sizeof (GElf_Phdr));
18150Sstevel@tonic-gate 		else
18160Sstevel@tonic-gate 			core_phdr_to_gelf(php, &phdr);
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 		switch (phdr.p_type) {
18190Sstevel@tonic-gate 		case PT_NOTE:
18200Sstevel@tonic-gate 			note_phdr = phdr;
18210Sstevel@tonic-gate 			notes++;
18220Sstevel@tonic-gate 			break;
18230Sstevel@tonic-gate 
18240Sstevel@tonic-gate 		case PT_LOAD:
18250Sstevel@tonic-gate 			if (core_add_mapping(P, &phdr) == -1) {
18260Sstevel@tonic-gate 				*perr = G_STRANGE;
18270Sstevel@tonic-gate 				free(phbuf);
18280Sstevel@tonic-gate 				goto err;
18290Sstevel@tonic-gate 			}
18300Sstevel@tonic-gate 			break;
18310Sstevel@tonic-gate 		}
18320Sstevel@tonic-gate 
18330Sstevel@tonic-gate 		php = (char *)php + core.e_hdr.e_phentsize;
18340Sstevel@tonic-gate 	}
18350Sstevel@tonic-gate 
18360Sstevel@tonic-gate 	free(phbuf);
18370Sstevel@tonic-gate 
18380Sstevel@tonic-gate 	Psort_mappings(P);
18390Sstevel@tonic-gate 
18400Sstevel@tonic-gate 	/*
18410Sstevel@tonic-gate 	 * If we couldn't find anything of type PT_NOTE, or only one PT_NOTE
18420Sstevel@tonic-gate 	 * was present, abort.  The core file is either corrupt or too old.
18430Sstevel@tonic-gate 	 */
18440Sstevel@tonic-gate 	if (notes == 0 || notes == 1) {
18450Sstevel@tonic-gate 		*perr = G_NOTE;
18460Sstevel@tonic-gate 		goto err;
18470Sstevel@tonic-gate 	}
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	/*
18500Sstevel@tonic-gate 	 * Advance the seek pointer to the start of the PT_NOTE data
18510Sstevel@tonic-gate 	 */
18520Sstevel@tonic-gate 	if (lseek64(P->asfd, note_phdr.p_offset, SEEK_SET) == (off64_t)-1) {
18530Sstevel@tonic-gate 		dprintf("Pgrab_core: failed to lseek to PT_NOTE data\n");
18540Sstevel@tonic-gate 		*perr = G_STRANGE;
18550Sstevel@tonic-gate 		goto err;
18560Sstevel@tonic-gate 	}
18570Sstevel@tonic-gate 
18580Sstevel@tonic-gate 	/*
18590Sstevel@tonic-gate 	 * Now process the PT_NOTE structures.  Each one is preceded by
18600Sstevel@tonic-gate 	 * an Elf{32/64}_Nhdr structure describing its type and size.
18610Sstevel@tonic-gate 	 *
18620Sstevel@tonic-gate 	 *  +--------+
18630Sstevel@tonic-gate 	 *  | header |
18640Sstevel@tonic-gate 	 *  +--------+
18650Sstevel@tonic-gate 	 *  | name   |
18660Sstevel@tonic-gate 	 *  | ...    |
18670Sstevel@tonic-gate 	 *  +--------+
18680Sstevel@tonic-gate 	 *  | desc   |
18690Sstevel@tonic-gate 	 *  | ...    |
18700Sstevel@tonic-gate 	 *  +--------+
18710Sstevel@tonic-gate 	 */
18720Sstevel@tonic-gate 	for (nleft = note_phdr.p_filesz; nleft > 0; ) {
18730Sstevel@tonic-gate 		Elf64_Nhdr nhdr;
18740Sstevel@tonic-gate 		off64_t off, namesz;
18750Sstevel@tonic-gate 
18760Sstevel@tonic-gate 		/*
18770Sstevel@tonic-gate 		 * Although <sys/elf.h> defines both Elf32_Nhdr and Elf64_Nhdr
18780Sstevel@tonic-gate 		 * as different types, they are both of the same content and
18790Sstevel@tonic-gate 		 * size, so we don't need to worry about 32/64 conversion here.
18800Sstevel@tonic-gate 		 */
18810Sstevel@tonic-gate 		if (read(P->asfd, &nhdr, sizeof (nhdr)) != sizeof (nhdr)) {
18820Sstevel@tonic-gate 			dprintf("Pgrab_core: failed to read ELF note header\n");
18830Sstevel@tonic-gate 			*perr = G_NOTE;
18840Sstevel@tonic-gate 			goto err;
18850Sstevel@tonic-gate 		}
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 		/*
18880Sstevel@tonic-gate 		 * According to the System V ABI, the amount of padding
18890Sstevel@tonic-gate 		 * following the name field should align the description
18900Sstevel@tonic-gate 		 * field on a 4 byte boundary for 32-bit binaries or on an 8
18910Sstevel@tonic-gate 		 * byte boundary for 64-bit binaries. However, this change
18920Sstevel@tonic-gate 		 * was not made correctly during the 64-bit port so all
18930Sstevel@tonic-gate 		 * descriptions can assume only 4-byte alignment. We ignore
18940Sstevel@tonic-gate 		 * the name field and the padding to 4-byte alignment.
18950Sstevel@tonic-gate 		 */
18960Sstevel@tonic-gate 		namesz = P2ROUNDUP((off64_t)nhdr.n_namesz, (off64_t)4);
18970Sstevel@tonic-gate 		if (lseek64(P->asfd, namesz, SEEK_CUR) == (off64_t)-1) {
18980Sstevel@tonic-gate 			dprintf("failed to seek past name and padding\n");
18990Sstevel@tonic-gate 			*perr = G_STRANGE;
19000Sstevel@tonic-gate 			goto err;
19010Sstevel@tonic-gate 		}
19020Sstevel@tonic-gate 
19030Sstevel@tonic-gate 		dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",
19040Sstevel@tonic-gate 		    nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);
19050Sstevel@tonic-gate 
19060Sstevel@tonic-gate 		off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);
19070Sstevel@tonic-gate 
19080Sstevel@tonic-gate 		/*
19090Sstevel@tonic-gate 		 * Invoke the note handler function from our table
19100Sstevel@tonic-gate 		 */
19110Sstevel@tonic-gate 		if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
19120Sstevel@tonic-gate 			if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
19130Sstevel@tonic-gate 				*perr = G_NOTE;
19140Sstevel@tonic-gate 				goto err;
19150Sstevel@tonic-gate 			}
19160Sstevel@tonic-gate 		} else
19170Sstevel@tonic-gate 			(void) note_notsup(P, nhdr.n_descsz);
19180Sstevel@tonic-gate 
19190Sstevel@tonic-gate 		/*
19200Sstevel@tonic-gate 		 * Seek past the current note data to the next Elf_Nhdr
19210Sstevel@tonic-gate 		 */
19220Sstevel@tonic-gate 		if (lseek64(P->asfd, off + nhdr.n_descsz,
19230Sstevel@tonic-gate 		    SEEK_SET) == (off64_t)-1) {
19240Sstevel@tonic-gate 			dprintf("Pgrab_core: failed to seek to next nhdr\n");
19250Sstevel@tonic-gate 			*perr = G_STRANGE;
19260Sstevel@tonic-gate 			goto err;
19270Sstevel@tonic-gate 		}
19280Sstevel@tonic-gate 
19290Sstevel@tonic-gate 		/*
19300Sstevel@tonic-gate 		 * Subtract the size of the header and its data from what
19310Sstevel@tonic-gate 		 * we have left to process.
19320Sstevel@tonic-gate 		 */
19330Sstevel@tonic-gate 		nleft -= sizeof (nhdr) + namesz + nhdr.n_descsz;
19340Sstevel@tonic-gate 	}
19350Sstevel@tonic-gate 
19360Sstevel@tonic-gate 	if (nleft != 0) {
19370Sstevel@tonic-gate 		dprintf("Pgrab_core: note section malformed\n");
19380Sstevel@tonic-gate 		*perr = G_STRANGE;
19390Sstevel@tonic-gate 		goto err;
19400Sstevel@tonic-gate 	}
19410Sstevel@tonic-gate 
19420Sstevel@tonic-gate 	if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {
19430Sstevel@tonic-gate 		pagesize = getpagesize();
19440Sstevel@tonic-gate 		dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);
19450Sstevel@tonic-gate 	}
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate 	/*
19480Sstevel@tonic-gate 	 * Locate and label the mappings corresponding to the end of the
19490Sstevel@tonic-gate 	 * heap (MA_BREAK) and the base of the stack (MA_STACK).
19500Sstevel@tonic-gate 	 */
19510Sstevel@tonic-gate 	if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&
19520Sstevel@tonic-gate 	    (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +
19530Sstevel@tonic-gate 	    P->status.pr_brksize - 1)) != NULL)
19540Sstevel@tonic-gate 		brk_mp->map_pmap.pr_mflags |= MA_BREAK;
19550Sstevel@tonic-gate 	else
19560Sstevel@tonic-gate 		brk_mp = NULL;
19570Sstevel@tonic-gate 
19580Sstevel@tonic-gate 	if ((stk_mp = Paddr2mptr(P, P->status.pr_stkbase)) != NULL)
19590Sstevel@tonic-gate 		stk_mp->map_pmap.pr_mflags |= MA_STACK;
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate 	/*
19620Sstevel@tonic-gate 	 * At this point, we have enough information to look for the
19630Sstevel@tonic-gate 	 * executable and open it: we have access to the auxv, a psinfo_t,
19640Sstevel@tonic-gate 	 * and the ability to read from mappings provided by the core file.
19650Sstevel@tonic-gate 	 */
19660Sstevel@tonic-gate 	(void) Pfindexec(P, aout_path, core_exec_open, &aout);
19670Sstevel@tonic-gate 	dprintf("P->execname = \"%s\"\n", P->execname ? P->execname : "NULL");
19680Sstevel@tonic-gate 	execname = P->execname ? P->execname : "a.out";
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate 	/*
19710Sstevel@tonic-gate 	 * Iterate through the sections, looking for the .dynamic and .interp
19720Sstevel@tonic-gate 	 * sections.  If we encounter them, remember their section pointers.
19730Sstevel@tonic-gate 	 */
19740Sstevel@tonic-gate 	for (scn = NULL; (scn = elf_nextscn(aout.e_elf, scn)) != NULL; ) {
19750Sstevel@tonic-gate 		char *sname;
19760Sstevel@tonic-gate 
19770Sstevel@tonic-gate 		if ((gelf_getshdr(scn, &shdr) == NULL) ||
19780Sstevel@tonic-gate 		    (sname = elf_strptr(aout.e_elf, aout.e_hdr.e_shstrndx,
19790Sstevel@tonic-gate 		    (size_t)shdr.sh_name)) == NULL)
19800Sstevel@tonic-gate 			continue;
19810Sstevel@tonic-gate 
19820Sstevel@tonic-gate 		if (strcmp(sname, ".interp") == 0)
19830Sstevel@tonic-gate 			intp_scn = scn;
19840Sstevel@tonic-gate 	}
19850Sstevel@tonic-gate 
19860Sstevel@tonic-gate 	/*
19870Sstevel@tonic-gate 	 * Get the AT_BASE auxv element.  If this is missing (-1), then
19880Sstevel@tonic-gate 	 * we assume this is a statically-linked executable.
19890Sstevel@tonic-gate 	 */
19900Sstevel@tonic-gate 	base_addr = Pgetauxval(P, AT_BASE);
19910Sstevel@tonic-gate 
19920Sstevel@tonic-gate 	/*
19930Sstevel@tonic-gate 	 * In order to get librtld_db initialized, we'll need to identify
19940Sstevel@tonic-gate 	 * and name the mapping corresponding to the run-time linker.  The
19950Sstevel@tonic-gate 	 * AT_BASE auxv element tells us the address where it was mapped,
19960Sstevel@tonic-gate 	 * and the .interp section of the executable tells us its path.
19970Sstevel@tonic-gate 	 * If for some reason that doesn't pan out, just use ld.so.1.
19980Sstevel@tonic-gate 	 */
19990Sstevel@tonic-gate 	if (intp_scn != NULL && (dp = elf_getdata(intp_scn, NULL)) != NULL &&
20000Sstevel@tonic-gate 	    dp->d_size != 0) {
20010Sstevel@tonic-gate 		dprintf(".interp = <%s>\n", (char *)dp->d_buf);
20020Sstevel@tonic-gate 		interp = dp->d_buf;
20030Sstevel@tonic-gate 
20040Sstevel@tonic-gate 	} else if (base_addr != (uintptr_t)-1L) {
20050Sstevel@tonic-gate 		if (P->core->core_dmodel == PR_MODEL_LP64)
20060Sstevel@tonic-gate 			interp = "/usr/lib/64/ld.so.1";
20070Sstevel@tonic-gate 		else
20080Sstevel@tonic-gate 			interp = "/usr/lib/ld.so.1";
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate 		dprintf(".interp section is missing or could not be read; "
20110Sstevel@tonic-gate 		    "defaulting to %s\n", interp);
20120Sstevel@tonic-gate 	} else
20130Sstevel@tonic-gate 		dprintf("detected statically linked executable\n");
20140Sstevel@tonic-gate 
20150Sstevel@tonic-gate 	/*
20160Sstevel@tonic-gate 	 * If we have an AT_BASE element, name the mapping at that address
20170Sstevel@tonic-gate 	 * using the interpreter pathname.  Name the corresponding data
20180Sstevel@tonic-gate 	 * mapping after the interpreter as well.
20190Sstevel@tonic-gate 	 */
20200Sstevel@tonic-gate 	if (base_addr != (uintptr_t)-1L) {
20210Sstevel@tonic-gate 		elf_file_t intf;
20220Sstevel@tonic-gate 
20230Sstevel@tonic-gate 		P->map_ldso = core_name_mapping(P, base_addr, interp);
20240Sstevel@tonic-gate 
20250Sstevel@tonic-gate 		if (core_elf_open(&intf, interp, ET_DYN, NULL) == 0) {
20260Sstevel@tonic-gate 			rd_loadobj_t rl;
20270Sstevel@tonic-gate 			map_info_t *dmp;
20280Sstevel@tonic-gate 
20290Sstevel@tonic-gate 			rl.rl_base = base_addr;
20300Sstevel@tonic-gate 			dmp = core_find_data(P, intf.e_elf, &rl);
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate 			if (dmp != NULL) {
20330Sstevel@tonic-gate 				dprintf("renamed data at %p to %s\n",
20340Sstevel@tonic-gate 				    (void *)rl.rl_data_base, interp);
20350Sstevel@tonic-gate 				(void) strncpy(dmp->map_pmap.pr_mapname,
20360Sstevel@tonic-gate 				    interp, PRMAPSZ);
20370Sstevel@tonic-gate 				dmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
20380Sstevel@tonic-gate 			}
20390Sstevel@tonic-gate 		}
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate 		core_elf_close(&intf);
20420Sstevel@tonic-gate 	}
20430Sstevel@tonic-gate 
20440Sstevel@tonic-gate 	/*
20450Sstevel@tonic-gate 	 * If we have an AT_ENTRY element, name the mapping at that address
20460Sstevel@tonic-gate 	 * using the special name "a.out" just like /proc does.
20470Sstevel@tonic-gate 	 */
20480Sstevel@tonic-gate 	if ((addr = Pgetauxval(P, AT_ENTRY)) != (uintptr_t)-1L)
20490Sstevel@tonic-gate 		P->map_exec = core_name_mapping(P, addr, "a.out");
20500Sstevel@tonic-gate 
20510Sstevel@tonic-gate 	/*
20520Sstevel@tonic-gate 	 * If we're a statically linked executable, then just locate the
20530Sstevel@tonic-gate 	 * executable's text and data and name them after the executable.
20540Sstevel@tonic-gate 	 */
20550Sstevel@tonic-gate 	if (base_addr == (uintptr_t)-1L) {
20560Sstevel@tonic-gate 		map_info_t *tmp, *dmp;
20570Sstevel@tonic-gate 		file_info_t *fp;
20580Sstevel@tonic-gate 		rd_loadobj_t rl;
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 		if ((tmp = core_find_text(P, aout.e_elf, &rl)) != NULL &&
20610Sstevel@tonic-gate 		    (dmp = core_find_data(P, aout.e_elf, &rl)) != NULL) {
20620Sstevel@tonic-gate 			(void) strncpy(tmp->map_pmap.pr_mapname,
20630Sstevel@tonic-gate 			    execname, PRMAPSZ);
20640Sstevel@tonic-gate 			tmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
20650Sstevel@tonic-gate 			(void) strncpy(dmp->map_pmap.pr_mapname,
20660Sstevel@tonic-gate 			    execname, PRMAPSZ);
20670Sstevel@tonic-gate 			dmp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0';
20680Sstevel@tonic-gate 		}
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate 		if ((P->map_exec = tmp) != NULL &&
20710Sstevel@tonic-gate 		    (fp = malloc(sizeof (file_info_t))) != NULL) {
20720Sstevel@tonic-gate 
20730Sstevel@tonic-gate 			(void) memset(fp, 0, sizeof (file_info_t));
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate 			list_link(fp, &P->file_head);
20760Sstevel@tonic-gate 			tmp->map_file = fp;
20770Sstevel@tonic-gate 			P->num_files++;
20780Sstevel@tonic-gate 
20790Sstevel@tonic-gate 			fp->file_ref = 1;
20800Sstevel@tonic-gate 			fp->file_fd = -1;
20810Sstevel@tonic-gate 
20820Sstevel@tonic-gate 			fp->file_lo = malloc(sizeof (rd_loadobj_t));
20830Sstevel@tonic-gate 			fp->file_lname = strdup(execname);
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 			if (fp->file_lo)
20860Sstevel@tonic-gate 				*fp->file_lo = rl;
20870Sstevel@tonic-gate 			if (fp->file_lname)
20880Sstevel@tonic-gate 				fp->file_lbase = basename(fp->file_lname);
20897675SEdward.Pilatowicz@Sun.COM 			if (fp->file_rname)
20907675SEdward.Pilatowicz@Sun.COM 				fp->file_rbase = basename(fp->file_rname);
20910Sstevel@tonic-gate 
20920Sstevel@tonic-gate 			(void) strcpy(fp->file_pname,
20930Sstevel@tonic-gate 			    P->mappings[0].map_pmap.pr_mapname);
20940Sstevel@tonic-gate 			fp->file_map = tmp;
20950Sstevel@tonic-gate 
20960Sstevel@tonic-gate 			Pbuild_file_symtab(P, fp);
20970Sstevel@tonic-gate 
20980Sstevel@tonic-gate 			if (dmp != NULL) {
20990Sstevel@tonic-gate 				dmp->map_file = fp;
21000Sstevel@tonic-gate 				fp->file_ref++;
21010Sstevel@tonic-gate 			}
21020Sstevel@tonic-gate 		}
21030Sstevel@tonic-gate 	}
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	core_elf_close(&aout);
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate 	/*
21080Sstevel@tonic-gate 	 * We now have enough information to initialize librtld_db.
21090Sstevel@tonic-gate 	 * After it warms up, we can iterate through the load object chain
21100Sstevel@tonic-gate 	 * in the core, which will allow us to construct the file info
21110Sstevel@tonic-gate 	 * we need to provide symbol information for the other shared
21120Sstevel@tonic-gate 	 * libraries, and also to fill in the missing mapping names.
21130Sstevel@tonic-gate 	 */
21140Sstevel@tonic-gate 	rd_log(_libproc_debug);
21150Sstevel@tonic-gate 
21160Sstevel@tonic-gate 	if ((P->rap = rd_new(P)) != NULL) {
21170Sstevel@tonic-gate 		(void) rd_loadobj_iter(P->rap, (rl_iter_f *)
21180Sstevel@tonic-gate 		    core_iter_mapping, P);
21190Sstevel@tonic-gate 
21200Sstevel@tonic-gate 		if (P->core->core_errno != 0) {
21210Sstevel@tonic-gate 			errno = P->core->core_errno;
21220Sstevel@tonic-gate 			*perr = G_STRANGE;
21230Sstevel@tonic-gate 			goto err;
21240Sstevel@tonic-gate 		}
21250Sstevel@tonic-gate 	} else
21260Sstevel@tonic-gate 		dprintf("failed to initialize rtld_db agent\n");
21270Sstevel@tonic-gate 
21280Sstevel@tonic-gate 	/*
21290Sstevel@tonic-gate 	 * If there are sections, load them and process the data from any
21300Sstevel@tonic-gate 	 * sections that we can use to annotate the file_info_t's.
21310Sstevel@tonic-gate 	 */
21320Sstevel@tonic-gate 	core_load_shdrs(P, &core);
21330Sstevel@tonic-gate 
21340Sstevel@tonic-gate 	/*
21350Sstevel@tonic-gate 	 * If we previously located a stack or break mapping, and they are
21360Sstevel@tonic-gate 	 * still anonymous, we now assume that they were MAP_ANON mappings.
21370Sstevel@tonic-gate 	 * If brk_mp turns out to now have a name, then the heap is still
21380Sstevel@tonic-gate 	 * sitting at the end of the executable's data+bss mapping: remove
21390Sstevel@tonic-gate 	 * the previous MA_BREAK setting to be consistent with /proc.
21400Sstevel@tonic-gate 	 */
21410Sstevel@tonic-gate 	if (stk_mp != NULL && stk_mp->map_pmap.pr_mapname[0] == '\0')
21420Sstevel@tonic-gate 		stk_mp->map_pmap.pr_mflags |= MA_ANON;
21430Sstevel@tonic-gate 	if (brk_mp != NULL && brk_mp->map_pmap.pr_mapname[0] == '\0')
21440Sstevel@tonic-gate 		brk_mp->map_pmap.pr_mflags |= MA_ANON;
21450Sstevel@tonic-gate 	else if (brk_mp != NULL)
21460Sstevel@tonic-gate 		brk_mp->map_pmap.pr_mflags &= ~MA_BREAK;
21470Sstevel@tonic-gate 
21480Sstevel@tonic-gate 	*perr = 0;
21490Sstevel@tonic-gate 	return (P);
21500Sstevel@tonic-gate 
21510Sstevel@tonic-gate err:
21520Sstevel@tonic-gate 	Pfree(P);
21530Sstevel@tonic-gate 	core_elf_close(&aout);
21540Sstevel@tonic-gate 	return (NULL);
21550Sstevel@tonic-gate }
21560Sstevel@tonic-gate 
21570Sstevel@tonic-gate /*
21580Sstevel@tonic-gate  * Grab a core file using a pathname.  We just open it and call Pfgrab_core().
21590Sstevel@tonic-gate  */
21600Sstevel@tonic-gate struct ps_prochandle *
Pgrab_core(const char * core,const char * aout,int gflag,int * perr)21610Sstevel@tonic-gate Pgrab_core(const char *core, const char *aout, int gflag, int *perr)
21620Sstevel@tonic-gate {
21630Sstevel@tonic-gate 	int fd, oflag = (gflag & PGRAB_RDONLY) ? O_RDONLY : O_RDWR;
21640Sstevel@tonic-gate 
21650Sstevel@tonic-gate 	if ((fd = open64(core, oflag)) >= 0)
21660Sstevel@tonic-gate 		return (Pfgrab_core(fd, aout, perr));
21670Sstevel@tonic-gate 
21680Sstevel@tonic-gate 	if (errno != ENOENT)
21690Sstevel@tonic-gate 		*perr = G_STRANGE;
21700Sstevel@tonic-gate 	else
21710Sstevel@tonic-gate 		*perr = G_NOCORE;
21720Sstevel@tonic-gate 
21730Sstevel@tonic-gate 	return (NULL);
21740Sstevel@tonic-gate }
2175