17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59acbbeafSnn  * Common Development and Distribution License (the "License").
69acbbeafSnn  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
225240bea1SRod Evans  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include	<stdlib.h>
277c478bd9Sstevel@tonic-gate #include	<stdio.h>
287c478bd9Sstevel@tonic-gate #include	<proc_service.h>
297c478bd9Sstevel@tonic-gate #include	<link.h>
307c478bd9Sstevel@tonic-gate #include	<rtld_db.h>
317c478bd9Sstevel@tonic-gate #include	<rtld.h>
32*57ef7aa9SRod Evans #include	<alist.h>
337c478bd9Sstevel@tonic-gate #include	<_rtld_db.h>
347c478bd9Sstevel@tonic-gate #include	<msg.h>
359acbbeafSnn #include	<limits.h>
369acbbeafSnn #include	<string.h>
379acbbeafSnn #include	<sys/param.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * 64-bit builds are going to compile this module twice, the
417c478bd9Sstevel@tonic-gate  * second time with _ELF64 defined.  These defines should make
427c478bd9Sstevel@tonic-gate  * all the necessary adjustments to the code.
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate #ifdef _LP64
457c478bd9Sstevel@tonic-gate #ifdef _ELF64
467c478bd9Sstevel@tonic-gate #define	_rd_event_enable32	_rd_event_enable64
477c478bd9Sstevel@tonic-gate #define	_rd_event_getmsg32	_rd_event_getmsg64
4822872efbSedp #define	_rd_get_dyns32		_rd_get_dyns64
4922872efbSedp #define	_rd_get_ehdr32		_rd_get_ehdr64
507c478bd9Sstevel@tonic-gate #define	_rd_objpad_enable32	_rd_objpad_enable64
517c478bd9Sstevel@tonic-gate #define	_rd_loadobj_iter32	_rd_loadobj_iter64
5222872efbSedp #define	_rd_reset32		_rd_reset64
537c478bd9Sstevel@tonic-gate #define	find_dynamic_ent32	find_dynamic_ent64
5422872efbSedp #define	validate_rdebug32	validate_rdebug64
55*57ef7aa9SRod Evans #define	TAPlist			APlist
56*57ef7aa9SRod Evans #define	TLm_list		Lm_list
57adbfe822Srie #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_64
587c478bd9Sstevel@tonic-gate #else	/* ELF32 */
597c478bd9Sstevel@tonic-gate #define	Rt_map			Rt_map32
607c478bd9Sstevel@tonic-gate #define	Rtld_db_priv		Rtld_db_priv32
61*57ef7aa9SRod Evans #define	TAPlist			APlist32
62*57ef7aa9SRod Evans #define	TLm_list		Lm_list32
63adbfe822Srie #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
647c478bd9Sstevel@tonic-gate #endif	/* _ELF64 */
657c478bd9Sstevel@tonic-gate #else	/* _LP64 */
66*57ef7aa9SRod Evans #define	TAPlist			APlist
67*57ef7aa9SRod Evans #define	TLm_list		Lm_list
68adbfe822Srie #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
697c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
707c478bd9Sstevel@tonic-gate 
715eae5a6fSedp /*
725eae5a6fSedp  * BrandZ added ps_pbrandname().  Many debuggers that link directly
735eae5a6fSedp  * against librtld_db.so may not implement this interface.  Hence
745eae5a6fSedp  * we won't call the function directly, instead we'll try to look it
755eae5a6fSedp  * up using the linker first and only invoke it if we find it.
765eae5a6fSedp  */
775eae5a6fSedp typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
785eae5a6fSedp     char *, size_t);
795eae5a6fSedp 
8022872efbSedp rd_err_e
8122872efbSedp validate_rdebug32(struct rd_agent *rap)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
847c478bd9Sstevel@tonic-gate 	psaddr_t		db_privp;
857c478bd9Sstevel@tonic-gate 	Rtld_db_priv		db_priv;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	if (rap->rd_rdebug == 0)
887c478bd9Sstevel@tonic-gate 		return (RD_ERR);
897c478bd9Sstevel@tonic-gate 	/*
907c478bd9Sstevel@tonic-gate 	 * The rtld_db_priv structure contains both the traditional (exposed)
917c478bd9Sstevel@tonic-gate 	 * r_debug structure as well as private data only available to
927c478bd9Sstevel@tonic-gate 	 * this library.
937c478bd9Sstevel@tonic-gate 	 */
947c478bd9Sstevel@tonic-gate 	db_privp = rap->rd_rdebug;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	/*
977c478bd9Sstevel@tonic-gate 	 * Verify that librtld_db & rtld are at the proper revision
987c478bd9Sstevel@tonic-gate 	 * levels.
997c478bd9Sstevel@tonic-gate 	 */
1007c478bd9Sstevel@tonic-gate 	if (ps_pread(php, db_privp, (char *)&db_priv,
1017c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
1027c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
1039acbbeafSnn 		    EC_ADDR(db_privp)));
1047c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
1087c478bd9Sstevel@tonic-gate 	    (db_priv.rtd_version > R_RTLDDB_VERSION)) {
1097c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
1109acbbeafSnn 		    db_priv.rtd_version, R_RTLDDB_VERSION));
1117c478bd9Sstevel@tonic-gate 		return (RD_NOCAPAB);
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	/*
1157c478bd9Sstevel@tonic-gate 	 * Is the image being examined from a core file or not.
1167c478bd9Sstevel@tonic-gate 	 * If it is a core file then the following write will fail.
1177c478bd9Sstevel@tonic-gate 	 */
1187c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, db_privp, (char *)&db_priv,
1197c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK)
1207c478bd9Sstevel@tonic-gate 		rap->rd_flags |= RDF_FL_COREFILE;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/*
1237c478bd9Sstevel@tonic-gate 	 * If this *is not* a core file then rtld_db & ld.so.1 are
1247c478bd9Sstevel@tonic-gate 	 * considered tightly coupled.  If the versions of our private
1257c478bd9Sstevel@tonic-gate 	 * data structures don't match - fail!
1267c478bd9Sstevel@tonic-gate 	 */
1277c478bd9Sstevel@tonic-gate 	if (((rap->rd_flags & RDF_FL_COREFILE) == 0) &&
1287c478bd9Sstevel@tonic-gate 	    (db_priv.rtd_version != R_RTLDDB_VERSION)) {
1297c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
1309acbbeafSnn 		    db_priv.rtd_version, R_RTLDDB_VERSION));
1317c478bd9Sstevel@tonic-gate 		return (RD_NOCAPAB);
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	rap->rd_rdebugvers = db_priv.rtd_version;
1357c478bd9Sstevel@tonic-gate 	rap->rd_rtlddbpriv = db_privp;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
1389acbbeafSnn 	    R_RTLDDB_VERSION, rap->rd_rdebugvers,
1399acbbeafSnn 	    rap->rd_flags & RDF_FL_COREFILE));
1407c478bd9Sstevel@tonic-gate 	return (RD_OK);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate rd_err_e
1457c478bd9Sstevel@tonic-gate find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
1467c478bd9Sstevel@tonic-gate 	Xword dyntag, Dyn *dyn)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
1497c478bd9Sstevel@tonic-gate 	Dyn			d;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	d.d_tag = DT_NULL;
1527c478bd9Sstevel@tonic-gate 	do {
1537c478bd9Sstevel@tonic-gate 		if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
1547c478bd9Sstevel@tonic-gate 		    PS_OK) {
1557c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
1569acbbeafSnn 			    EC_ADDR(dynaddr)));
1577c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
1587c478bd9Sstevel@tonic-gate 		}
1597c478bd9Sstevel@tonic-gate 		dynaddr += sizeof (d);
1607c478bd9Sstevel@tonic-gate 		if (d.d_tag == dyntag)
1617c478bd9Sstevel@tonic-gate 			break;
1627c478bd9Sstevel@tonic-gate 	} while (d.d_tag != DT_NULL);
1637c478bd9Sstevel@tonic-gate 	if (d.d_tag == dyntag) {
1647c478bd9Sstevel@tonic-gate 		*dyn = d;
1657c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
1667c478bd9Sstevel@tonic-gate 		    EC_ADDR(d.d_un.d_val)));
1677c478bd9Sstevel@tonic-gate 		return (RD_OK);
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
1707c478bd9Sstevel@tonic-gate 	return (RD_DBERR);
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate 
1739acbbeafSnn extern char rtld_db_helper_path[MAXPATHLEN];
1749acbbeafSnn 
1757c478bd9Sstevel@tonic-gate rd_err_e
1767c478bd9Sstevel@tonic-gate _rd_reset32(struct rd_agent *rap)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	psaddr_t		symaddr;
1797c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
1807c478bd9Sstevel@tonic-gate 	const auxv_t		*auxvp = NULL;
1817c478bd9Sstevel@tonic-gate 	rd_err_e		rc = RD_OK;
1829acbbeafSnn 	char			brandname[MAXPATHLEN];
1839acbbeafSnn 	char			brandlib[MAXPATHLEN];
1845eae5a6fSedp 	ps_pbrandname_fp_t	ps_pbrandname;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/*
1877c478bd9Sstevel@tonic-gate 	 * librtld_db attempts three different methods to find
1887c478bd9Sstevel@tonic-gate 	 * the r_debug structure which is required to
1897c478bd9Sstevel@tonic-gate 	 * initialize itself.  The methods are:
1907c478bd9Sstevel@tonic-gate 	 *	method1:
1917c478bd9Sstevel@tonic-gate 	 *		entirely independent of any text segment
1927c478bd9Sstevel@tonic-gate 	 *		and relies on the AT_SUN_LDDATA auxvector
1937c478bd9Sstevel@tonic-gate 	 *		to find the ld.so.1::rdebug structure.
1947c478bd9Sstevel@tonic-gate 	 *	method2:
1957c478bd9Sstevel@tonic-gate 	 *		lookup symbols in ld.so.1's symbol table
1967c478bd9Sstevel@tonic-gate 	 *		to find the r_debug symbol.
1977c478bd9Sstevel@tonic-gate 	 *	method3:
1987c478bd9Sstevel@tonic-gate 	 *		(old dbx method) dependent upon the
1997c478bd9Sstevel@tonic-gate 	 *		text segment/symbol table of the
2007c478bd9Sstevel@tonic-gate 	 *		executable and not ld.so.1.  We lookup the
2017c478bd9Sstevel@tonic-gate 	 *		_DYNAMIC symbol in the executable and look for
2027c478bd9Sstevel@tonic-gate 	 *		the DT_DEBUG entry in the .dynamic table.  This
2037c478bd9Sstevel@tonic-gate 	 *		points to rdebug.
2047c478bd9Sstevel@tonic-gate 	 *
2057c478bd9Sstevel@tonic-gate 	 * If none of that works - we fail.
2067c478bd9Sstevel@tonic-gate 	 */
2077c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
2087c478bd9Sstevel@tonic-gate 	/*
2097c478bd9Sstevel@tonic-gate 	 * Method1
2107c478bd9Sstevel@tonic-gate 	 *
2117c478bd9Sstevel@tonic-gate 	 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
2127c478bd9Sstevel@tonic-gate 	 */
2139acbbeafSnn 
2147c478bd9Sstevel@tonic-gate 	if (ps_pauxv(php, &auxvp) != PS_OK) {
2157c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
2167c478bd9Sstevel@tonic-gate 		rc = RD_ERR;
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	rap->rd_rdebug = 0;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	if (auxvp != NULL) {
2227c478bd9Sstevel@tonic-gate 		rc = RD_ERR;
2237c478bd9Sstevel@tonic-gate 		while (auxvp->a_type != AT_NULL) {
2247c478bd9Sstevel@tonic-gate 			if (auxvp->a_type == AT_SUN_LDDATA) {
2257c478bd9Sstevel@tonic-gate 				/* LINTED */
2267c478bd9Sstevel@tonic-gate 				rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
2277c478bd9Sstevel@tonic-gate 				LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
2287c478bd9Sstevel@tonic-gate 				    rap->rd_rdebug));
22922872efbSedp 				rc = validate_rdebug32(rap);
2307c478bd9Sstevel@tonic-gate 				break;
2317c478bd9Sstevel@tonic-gate 			}
2327c478bd9Sstevel@tonic-gate 			auxvp++;
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/*
2377c478bd9Sstevel@tonic-gate 	 * method2 - look for r_rdebug symbol in ld.so.1
2387c478bd9Sstevel@tonic-gate 	 */
2397c478bd9Sstevel@tonic-gate 	if (rc != RD_OK) {
2407c478bd9Sstevel@tonic-gate 		/*
2417c478bd9Sstevel@tonic-gate 		 * If the AT_SUN_LDDATA auxv vector is not present
2427c478bd9Sstevel@tonic-gate 		 * fall back on doing a symlookup of
2437c478bd9Sstevel@tonic-gate 		 * the r_debug symbol.  This is for backward
2447c478bd9Sstevel@tonic-gate 		 * compatiblity with older OS's
2457c478bd9Sstevel@tonic-gate 		 */
2467c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
2477c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
2487c478bd9Sstevel@tonic-gate 		    &symaddr) != PS_OK) {
2497c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
2509acbbeafSnn 			    MSG_ORIG(MSG_SYM_DEBUG)));
2517c478bd9Sstevel@tonic-gate 			rc = RD_DBERR;
2527c478bd9Sstevel@tonic-gate 		} else {
2537c478bd9Sstevel@tonic-gate 			rap->rd_rdebug = symaddr;
2547c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
2559acbbeafSnn 			    EC_ADDR(symaddr)));
25622872efbSedp 			rc = validate_rdebug32(rap);
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	/*
2627c478bd9Sstevel@tonic-gate 	 * method3 - find DT_DEBUG in the executables .dynamic section.
2637c478bd9Sstevel@tonic-gate 	 */
2647c478bd9Sstevel@tonic-gate 	if (rc != RD_OK) {
2657c478bd9Sstevel@tonic-gate 		Dyn	dyn;
2667c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
2677c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
2687c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
2697c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2707c478bd9Sstevel@tonic-gate 			return (rc);
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 		rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
2737c478bd9Sstevel@tonic-gate 		if (rc != RD_OK) {
2747c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2757c478bd9Sstevel@tonic-gate 			return (rc);
2767c478bd9Sstevel@tonic-gate 		}
2777c478bd9Sstevel@tonic-gate 		rap->rd_rdebug = dyn.d_un.d_ptr;
27822872efbSedp 		rc = validate_rdebug32(rap);
2797c478bd9Sstevel@tonic-gate 		if (rc != RD_OK) {
2807c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2817c478bd9Sstevel@tonic-gate 			return (rc);
2827c478bd9Sstevel@tonic-gate 		}
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2859acbbeafSnn 	/*
28622872efbSedp 	 * If we are debugging a branded executable, load the appropriate
28722872efbSedp 	 * helper library, and call its initialization routine.  Being unable
28822872efbSedp 	 * to load the helper library is not a critical error.  (Hopefully
28922872efbSedp 	 * we'll still be able to access some objects in the target.)
2909acbbeafSnn 	 */
2915eae5a6fSedp 	ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
29222872efbSedp 	while ((ps_pbrandname != NULL) &&
2935eae5a6fSedp 	    (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
2949acbbeafSnn 		const char *isa = "";
2959acbbeafSnn 
29622872efbSedp #ifdef _LP64
2979acbbeafSnn 		isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
29822872efbSedp #endif /* _LP64 */
2999acbbeafSnn 
3009acbbeafSnn 		if (rtld_db_helper_path[0] != '\0')
3019acbbeafSnn 			(void) snprintf(brandlib, MAXPATHLEN,
3029acbbeafSnn 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
3039acbbeafSnn 			    rtld_db_helper_path,
3049acbbeafSnn 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
3059acbbeafSnn 			    brandname);
3069acbbeafSnn 		else
3079acbbeafSnn 			(void) snprintf(brandlib, MAXPATHLEN,
3089acbbeafSnn 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH),
3099acbbeafSnn 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
3109acbbeafSnn 			    brandname);
3119acbbeafSnn 
31222872efbSedp 		rap->rd_helper.rh_dlhandle = dlopen(brandlib,
31322872efbSedp 		    RTLD_LAZY | RTLD_LOCAL);
31422872efbSedp 		if (rap->rd_helper.rh_dlhandle == NULL) {
3159acbbeafSnn 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
3169acbbeafSnn 			    brandlib));
31722872efbSedp 			break;
3189acbbeafSnn 		}
3199acbbeafSnn 
32022872efbSedp 		rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
32122872efbSedp 		    MSG_ORIG(MSG_SYM_BRANDOPS));
32222872efbSedp 		if (rap->rd_helper.rh_ops == NULL) {
3239acbbeafSnn 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
3249acbbeafSnn 			    brandlib));
32522872efbSedp 			(void) dlclose(rap->rd_helper.rh_dlhandle);
32622872efbSedp 			rap->rd_helper.rh_dlhandle = NULL;
32722872efbSedp 			break;
3289acbbeafSnn 		}
3299acbbeafSnn 
33022872efbSedp 		rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
33122872efbSedp 		    php);
3329acbbeafSnn 		if (rap->rd_helper.rh_data == NULL) {
3339acbbeafSnn 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
3349acbbeafSnn 			(void) dlclose(rap->rd_helper.rh_dlhandle);
3359acbbeafSnn 			rap->rd_helper.rh_dlhandle = NULL;
3369acbbeafSnn 			rap->rd_helper.rh_ops = NULL;
33722872efbSedp 			break;
33822872efbSedp 		}
33922872efbSedp 
34022872efbSedp 		LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
34122872efbSedp 		break;
342adbfe822Srie 
343adbfe822Srie 		/* NOTREACHED */
3449acbbeafSnn 	}
3459acbbeafSnn 
3467c478bd9Sstevel@tonic-gate 	if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
3477c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3487c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
3497c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3509acbbeafSnn 			    MSG_ORIG(MSG_SYM_PREINIT)));
3517c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 		rap->rd_preinit = symaddr;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3567c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
3577c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3589acbbeafSnn 			    MSG_ORIG(MSG_SYM_POSTINIT)));
3597c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
3607c478bd9Sstevel@tonic-gate 		}
3617c478bd9Sstevel@tonic-gate 		rap->rd_postinit = symaddr;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3647c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
3657c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3669acbbeafSnn 			    MSG_ORIG(MSG_SYM_DLACT)));
3677c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 		rap->rd_dlact = symaddr;
3707c478bd9Sstevel@tonic-gate 		rap->rd_tbinder = 0;
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	return (RD_OK);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
37622872efbSedp rd_err_e
37722872efbSedp _rd_get_ehdr32(struct rd_agent *rap,
37822872efbSedp     psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
37922872efbSedp {
38022872efbSedp 	struct ps_prochandle	*php = rap->rd_psp;
38122872efbSedp 	Shdr			shdr;
38222872efbSedp 
38322872efbSedp 	if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
38422872efbSedp 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
38522872efbSedp 		return (RD_ERR);
38622872efbSedp 	}
38722872efbSedp 	if (phnum == NULL)
38822872efbSedp 		return (RD_OK);
38922872efbSedp 
39022872efbSedp 	if (ehdr->e_phnum != PN_XNUM) {
39122872efbSedp 		*phnum = ehdr->e_phnum;
39222872efbSedp 		return (RD_OK);
39322872efbSedp 	}
39422872efbSedp 
39522872efbSedp 	/* deal with elf extended program headers */
39622872efbSedp 	if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
39722872efbSedp 		return (RD_ERR);
39822872efbSedp 
39922872efbSedp 	addr += ehdr->e_shoff;
40022872efbSedp 	if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
40122872efbSedp 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
40222872efbSedp 		return (RD_ERR);
40322872efbSedp 	}
40422872efbSedp 
40522872efbSedp 	if (shdr.sh_info == 0)
40622872efbSedp 		return (RD_ERR);
40722872efbSedp 
40822872efbSedp 	*phnum = shdr.sh_info;
40922872efbSedp 	return (RD_OK);
41022872efbSedp }
41122872efbSedp 
41222872efbSedp rd_err_e
41322872efbSedp _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
41422872efbSedp {
41522872efbSedp 	struct ps_prochandle	*php = rap->rd_psp;
41622872efbSedp 	rd_err_e		err;
41722872efbSedp 	uint_t			phnum;
41822872efbSedp 	Ehdr			ehdr;
41922872efbSedp 	Phdr			phdr;
42022872efbSedp 	Dyn			*dynp;
42122872efbSedp 	int			i;
42222872efbSedp 
42322872efbSedp 	/* We only need to muck with dyn elements for ET_DYN objects */
42422872efbSedp 	if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
42522872efbSedp 		return (err);
42622872efbSedp 
42722872efbSedp 	for (i = 0; i < phnum; i++) {
42822872efbSedp 		psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
42922872efbSedp 		if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
43022872efbSedp 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
43122872efbSedp 			return (RD_ERR);
43222872efbSedp 		}
43322872efbSedp 		if (phdr.p_type == PT_DYNAMIC)
43422872efbSedp 			break;
43522872efbSedp 	}
43622872efbSedp 	if (i == phnum)
43722872efbSedp 		return (RD_ERR);
43822872efbSedp 
43922872efbSedp 	if ((dynp = malloc(phdr.p_filesz)) == NULL)
44022872efbSedp 		return (RD_ERR);
44122872efbSedp 	if (ehdr.e_type == ET_DYN)
44222872efbSedp 		phdr.p_vaddr += addr;
44322872efbSedp 	if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
44422872efbSedp 		free(dynp);
44522872efbSedp 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
44622872efbSedp 		    EC_ADDR(phdr.p_vaddr)));
44722872efbSedp 		return (RD_ERR);
44822872efbSedp 	}
44922872efbSedp 
45022872efbSedp 	*dynpp = dynp;
451544fa60cSedp 	if (dynpp_sz != NULL)
452544fa60cSedp 		*dynpp_sz = phdr.p_filesz;
45322872efbSedp 	return (RD_OK);
45422872efbSedp }
45522872efbSedp 
4567c478bd9Sstevel@tonic-gate rd_err_e
4577c478bd9Sstevel@tonic-gate _rd_event_enable32(rd_agent_t *rap, int onoff)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
4607c478bd9Sstevel@tonic-gate 	Rtld_db_priv		rdb;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * Tell the debugged process that debugging is occuring
4657c478bd9Sstevel@tonic-gate 	 * This will enable the storing of event messages so that
4667c478bd9Sstevel@tonic-gate 	 * the can be gathered by the debugger.
4677c478bd9Sstevel@tonic-gate 	 */
4687c478bd9Sstevel@tonic-gate 	if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
4697c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
4707c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
4717c478bd9Sstevel@tonic-gate 		    EC_ADDR((uintptr_t)&rdb)));
4727c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	if (onoff)
4767c478bd9Sstevel@tonic-gate 		rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
4777c478bd9Sstevel@tonic-gate 	else
4787c478bd9Sstevel@tonic-gate 		rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
4817c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
4827c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
4837c478bd9Sstevel@tonic-gate 		    EC_ADDR((uintptr_t)&rdb)));
4847c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	return (RD_OK);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate rd_err_e
4927c478bd9Sstevel@tonic-gate _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate 	Rtld_db_priv	rdb;
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
4977c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
4987c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
4997c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rdebug)));
5007c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 	emsg->type = rdb.rtd_rdebug.r_rdevent;
5037c478bd9Sstevel@tonic-gate 	if (emsg->type == RD_DLACTIVITY) {
5047c478bd9Sstevel@tonic-gate 		switch (rdb.rtd_rdebug.r_state) {
5057c478bd9Sstevel@tonic-gate 			case RT_CONSISTENT:
5067c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_CONSISTENT;
5077c478bd9Sstevel@tonic-gate 				break;
5087c478bd9Sstevel@tonic-gate 			case RT_ADD:
5097c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_ADD;
5107c478bd9Sstevel@tonic-gate 				break;
5117c478bd9Sstevel@tonic-gate 			case RT_DELETE:
5127c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_DELETE;
5137c478bd9Sstevel@tonic-gate 				break;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 	} else
5167c478bd9Sstevel@tonic-gate 		emsg->u.state = RD_NOSTATE;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
5199acbbeafSnn 	    emsg->type, emsg->u.state));
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	return (RD_OK);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate rd_err_e
5267c478bd9Sstevel@tonic-gate _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
5277c478bd9Sstevel@tonic-gate {
5287c478bd9Sstevel@tonic-gate 	Rtld_db_priv		db_priv;
5297c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
5347c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
5357c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
5367c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
5377c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate #if	defined(_LP64) && !defined(_ELF64)
5407c478bd9Sstevel@tonic-gate 	/*LINTED*/
5417c478bd9Sstevel@tonic-gate 	db_priv.rtd_objpad = (uint32_t)padsize;
5427c478bd9Sstevel@tonic-gate #else
5437c478bd9Sstevel@tonic-gate 	db_priv.rtd_objpad = padsize;
5447c478bd9Sstevel@tonic-gate #endif
5457c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
5467c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
5477c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
5487c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
5497c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate 	return (RD_OK);
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate static rd_err_e
5557c478bd9Sstevel@tonic-gate iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
5560ef25df5SEdward Pilatowicz 	rl_iter_f *cb, void *client_data, uint_t *abort_iterp)
5577c478bd9Sstevel@tonic-gate {
5587c478bd9Sstevel@tonic-gate 	while (lmaddr) {
5597c478bd9Sstevel@tonic-gate 		Rt_map		rmap;
5607c478bd9Sstevel@tonic-gate 		rd_loadobj_t	lobj;
5617c478bd9Sstevel@tonic-gate 		int		i;
5627c478bd9Sstevel@tonic-gate 		ulong_t		off;
5637c478bd9Sstevel@tonic-gate 		Ehdr		ehdr;
5647c478bd9Sstevel@tonic-gate 		Phdr		phdr;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
5677c478bd9Sstevel@tonic-gate 		    sizeof (Rt_map)) != PS_OK) {
5687c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
5697c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
5707c478bd9Sstevel@tonic-gate 		}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 		/*
5737c478bd9Sstevel@tonic-gate 		 * As of 'VERSION5' we only report objects
5747c478bd9Sstevel@tonic-gate 		 * which have been fully relocated.  While the maps
5757c478bd9Sstevel@tonic-gate 		 * might be in a consistent state - if a object hasn't
5767c478bd9Sstevel@tonic-gate 		 * been relocated - it's not really ready for the debuggers
5777c478bd9Sstevel@tonic-gate 		 * to examine.  This is mostly due to the fact that we
5787c478bd9Sstevel@tonic-gate 		 * might still be mucking with the text-segment, if
5797c478bd9Sstevel@tonic-gate 		 * we are - we could conflict with any break-points
5807c478bd9Sstevel@tonic-gate 		 * the debuggers might have set.
5817c478bd9Sstevel@tonic-gate 		 */
5827c478bd9Sstevel@tonic-gate 		if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
5837c478bd9Sstevel@tonic-gate 			if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
5847c478bd9Sstevel@tonic-gate 				lmaddr = (psaddr_t)NEXT(&rmap);
5857c478bd9Sstevel@tonic-gate 				continue;
5867c478bd9Sstevel@tonic-gate 			}
5877c478bd9Sstevel@tonic-gate 		}
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 		lobj.rl_base = (psaddr_t)ADDR(&rmap);
5907c478bd9Sstevel@tonic-gate 		lobj.rl_flags = 0;
5917c478bd9Sstevel@tonic-gate 		lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
59222872efbSedp 		if ((rap->rd_helper.rh_ops != NULL) &&
59322872efbSedp 		    (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
59422872efbSedp 			lobj.rl_lmident =
59522872efbSedp 			    rap->rd_helper.rh_ops->rho_lmid;
5969acbbeafSnn 		else
5979acbbeafSnn 			lobj.rl_lmident = ident;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 		/*
6007c478bd9Sstevel@tonic-gate 		 * refnameaddr is only valid from a core file
6017c478bd9Sstevel@tonic-gate 		 * which is VERSION3 or greater.
6027c478bd9Sstevel@tonic-gate 		 */
6037c478bd9Sstevel@tonic-gate 		if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
6047c478bd9Sstevel@tonic-gate 			lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
6057c478bd9Sstevel@tonic-gate 			lobj.rl_bend = 0;
6067c478bd9Sstevel@tonic-gate 			lobj.rl_padstart = 0;
6077c478bd9Sstevel@tonic-gate 			lobj.rl_padend = 0;
6087c478bd9Sstevel@tonic-gate 		} else {
6097c478bd9Sstevel@tonic-gate 			lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
6107c478bd9Sstevel@tonic-gate 			lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
6117c478bd9Sstevel@tonic-gate 			lobj.rl_padstart = PADSTART(&rmap);
6127c478bd9Sstevel@tonic-gate 			lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 		}
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION2)
6177c478bd9Sstevel@tonic-gate 			if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
6187c478bd9Sstevel@tonic-gate 				lobj.rl_flags |= RD_FLG_MEM_OBJECT;
6197c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION2) {
6207c478bd9Sstevel@tonic-gate 			lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
6217c478bd9Sstevel@tonic-gate 		}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION4)
6247c478bd9Sstevel@tonic-gate 			lobj.rl_tlsmodid = TLSMODID(&rmap);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		/*
6277c478bd9Sstevel@tonic-gate 		 * Look for beginning of data segment.
6287c478bd9Sstevel@tonic-gate 		 *
6297c478bd9Sstevel@tonic-gate 		 * NOTE: the data segment can only be found for full
6307c478bd9Sstevel@tonic-gate 		 *	processes and not from core images.
6317c478bd9Sstevel@tonic-gate 		 */
6327c478bd9Sstevel@tonic-gate 		lobj.rl_data_base = 0;
6337c478bd9Sstevel@tonic-gate 		if (rap->rd_flags & RDF_FL_COREFILE)
6347c478bd9Sstevel@tonic-gate 			lobj.rl_data_base = 0;
6357c478bd9Sstevel@tonic-gate 		else {
6367c478bd9Sstevel@tonic-gate 			off = ADDR(&rmap);
6377c478bd9Sstevel@tonic-gate 			if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
6387c478bd9Sstevel@tonic-gate 			    sizeof (Ehdr)) != PS_OK) {
6397c478bd9Sstevel@tonic-gate 				LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
6407c478bd9Sstevel@tonic-gate 				return (RD_DBERR);
6417c478bd9Sstevel@tonic-gate 			}
6427c478bd9Sstevel@tonic-gate 			off += sizeof (Ehdr);
6437c478bd9Sstevel@tonic-gate 			for (i = 0; i < ehdr.e_phnum; i++) {
6447c478bd9Sstevel@tonic-gate 				if (ps_pread(rap->rd_psp, off, (char *)&phdr,
6457c478bd9Sstevel@tonic-gate 				    sizeof (Phdr)) != PS_OK) {
6467c478bd9Sstevel@tonic-gate 					LOG(ps_plog(MSG_ORIG(
6477c478bd9Sstevel@tonic-gate 					    MSG_DB_LKMAPFAIL)));
6487c478bd9Sstevel@tonic-gate 					return (RD_DBERR);
6497c478bd9Sstevel@tonic-gate 				}
6507c478bd9Sstevel@tonic-gate 				if ((phdr.p_type == PT_LOAD) &&
6517c478bd9Sstevel@tonic-gate 				    (phdr.p_flags & PF_W)) {
6527c478bd9Sstevel@tonic-gate 					lobj.rl_data_base = phdr.p_vaddr;
6537c478bd9Sstevel@tonic-gate 					if (ehdr.e_type == ET_DYN)
6547c478bd9Sstevel@tonic-gate 						lobj.rl_data_base +=
6559acbbeafSnn 						    ADDR(&rmap);
6567c478bd9Sstevel@tonic-gate 					break;
6577c478bd9Sstevel@tonic-gate 				}
6587c478bd9Sstevel@tonic-gate 				off += ehdr.e_phentsize;
6597c478bd9Sstevel@tonic-gate 			}
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 		/*
6637c478bd9Sstevel@tonic-gate 		 * When we transfer control to the client we free the
6647c478bd9Sstevel@tonic-gate 		 * lock and re-atain it after we've returned from the
6657c478bd9Sstevel@tonic-gate 		 * client.  This is to avoid any deadlock situations.
6667c478bd9Sstevel@tonic-gate 		 */
6677c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
6689acbbeafSnn 		    EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
6697c478bd9Sstevel@tonic-gate 		RDAGUNLOCK(rap);
6707c478bd9Sstevel@tonic-gate 		if ((*cb)(&lobj, client_data) == 0) {
6717c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
6727c478bd9Sstevel@tonic-gate 			RDAGLOCK(rap);
6730ef25df5SEdward Pilatowicz 			*abort_iterp = 1;
6747c478bd9Sstevel@tonic-gate 			break;
6757c478bd9Sstevel@tonic-gate 		}
6767c478bd9Sstevel@tonic-gate 		RDAGLOCK(rap);
6777c478bd9Sstevel@tonic-gate 		lmaddr = (psaddr_t)NEXT(&rmap);
6787c478bd9Sstevel@tonic-gate 	}
6797c478bd9Sstevel@tonic-gate 	return (RD_OK);
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 
6830ef25df5SEdward Pilatowicz static rd_err_e
6840ef25df5SEdward Pilatowicz _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data,
6850ef25df5SEdward Pilatowicz     uint_t *abort_iterp)
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	Rtld_db_priv	db_priv;
688*57ef7aa9SRod Evans 	TAPlist		apl;
689*57ef7aa9SRod Evans 	uintptr_t	datap, nitems;
690*57ef7aa9SRod Evans 	Addr		addr;
6917c478bd9Sstevel@tonic-gate 	rd_err_e	rc;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
6949acbbeafSnn 	    client_data));
6957c478bd9Sstevel@tonic-gate 
696*57ef7aa9SRod Evans 	if (cb == NULL) {
697*57ef7aa9SRod Evans 		LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
698*57ef7aa9SRod Evans 		return (RD_ERR);
699*57ef7aa9SRod Evans 	}
700*57ef7aa9SRod Evans 
7017c478bd9Sstevel@tonic-gate 	if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
7027c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
7037c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
7047c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
7057c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 
708*57ef7aa9SRod Evans 	if (db_priv.rtd_dynlmlst == NULL) {
7097c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
7109acbbeafSnn 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7117c478bd9Sstevel@tonic-gate 		return (RD_NOMAPS);
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
714*57ef7aa9SRod Evans 	if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr,
715*57ef7aa9SRod Evans 	    sizeof (Addr)) != PS_OK) {
7167c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
7179acbbeafSnn 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7187c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
721*57ef7aa9SRod Evans 	if (addr == NULL) {
7227c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
723*57ef7aa9SRod Evans 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7247c478bd9Sstevel@tonic-gate 		return (RD_NOMAPS);
7257c478bd9Sstevel@tonic-gate 	}
7267c478bd9Sstevel@tonic-gate 
727*57ef7aa9SRod Evans 	if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl,
728*57ef7aa9SRod Evans 	    sizeof (TAPlist)) != PS_OK) {
729*57ef7aa9SRod Evans 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
730*57ef7aa9SRod Evans 		    EC_ADDR((uintptr_t)addr)));
731*57ef7aa9SRod Evans 		return (RD_DBERR);
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 
734*57ef7aa9SRod Evans 	/*
735*57ef7aa9SRod Evans 	 * Iterate through each apl.ap_data[] entry.
736*57ef7aa9SRod Evans 	 */
737*57ef7aa9SRod Evans 	for (datap = (uintptr_t)((char *)(uintptr_t)addr +
738*57ef7aa9SRod Evans 	    ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0;
739*57ef7aa9SRod Evans 	    nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) {
740*57ef7aa9SRod Evans 		TLm_list	lm;
741*57ef7aa9SRod Evans 		ulong_t		ident;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 		/*
744*57ef7aa9SRod Evans 		 * Obtain the Lm_list address for this apl.ap_data[] entry.
7457c478bd9Sstevel@tonic-gate 		 */
746*57ef7aa9SRod Evans 		if (ps_pread(rap->rd_psp, (psaddr_t)datap, (char *)&addr,
747*57ef7aa9SRod Evans 		    sizeof (Addr)) != PS_OK) {
748*57ef7aa9SRod Evans 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
749*57ef7aa9SRod Evans 			    EC_ADDR(datap)));
7507c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
7517c478bd9Sstevel@tonic-gate 		}
7527c478bd9Sstevel@tonic-gate 
753*57ef7aa9SRod Evans 		/*
754*57ef7aa9SRod Evans 		 * Obtain the Lm_list data for this Lm_list address.
755*57ef7aa9SRod Evans 		 */
756*57ef7aa9SRod Evans 		if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm,
757*57ef7aa9SRod Evans 		    sizeof (TLm_list)) != PS_OK) {
758*57ef7aa9SRod Evans 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6),
759*57ef7aa9SRod Evans 			    EC_ADDR((uintptr_t)addr)));
7607c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
7617c478bd9Sstevel@tonic-gate 		}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 		/*
7647c478bd9Sstevel@tonic-gate 		 * Determine IDENT of current LM_LIST
7657c478bd9Sstevel@tonic-gate 		 */
766*57ef7aa9SRod Evans 		if (lm.lm_flags & LML_FLG_BASELM)
7677c478bd9Sstevel@tonic-gate 			ident = LM_ID_BASE;
768*57ef7aa9SRod Evans 		else if (lm.lm_flags & LML_FLG_RTLDLM)
7697c478bd9Sstevel@tonic-gate 			ident = LM_ID_LDSO;
7707c478bd9Sstevel@tonic-gate 		else
771*57ef7aa9SRod Evans 			ident = (ulong_t)addr;
7727c478bd9Sstevel@tonic-gate 
773*57ef7aa9SRod Evans 		if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head,
7740ef25df5SEdward Pilatowicz 		    cb, client_data, abort_iterp)) != RD_OK) {
7757c478bd9Sstevel@tonic-gate 			return (rc);
7767c478bd9Sstevel@tonic-gate 		}
7770ef25df5SEdward Pilatowicz 		if (*abort_iterp != 0)
7787c478bd9Sstevel@tonic-gate 			break;
7797c478bd9Sstevel@tonic-gate 	}
7809acbbeafSnn 
7810ef25df5SEdward Pilatowicz 	return (rc);
7820ef25df5SEdward Pilatowicz }
7830ef25df5SEdward Pilatowicz 
7840ef25df5SEdward Pilatowicz rd_err_e
7850ef25df5SEdward Pilatowicz _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
7860ef25df5SEdward Pilatowicz {
7875240bea1SRod Evans 	rd_err_e	rc, rc_brand = RD_OK;
7880ef25df5SEdward Pilatowicz 	uint_t		abort_iter = 0;
7890ef25df5SEdward Pilatowicz 
7900ef25df5SEdward Pilatowicz 	/* First iterate over the native target objects */
7910ef25df5SEdward Pilatowicz 	rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter);
7920ef25df5SEdward Pilatowicz 	if (abort_iter != 0)
7939acbbeafSnn 		return (rc);
7949acbbeafSnn 
7950ef25df5SEdward Pilatowicz 	/* Then iterate over any branded objects. */
7960ef25df5SEdward Pilatowicz 	if ((rap->rd_helper.rh_ops != NULL) &&
7970ef25df5SEdward Pilatowicz 	    (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL))
7980ef25df5SEdward Pilatowicz 		rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter(
7990ef25df5SEdward Pilatowicz 		    rap->rd_helper.rh_data, cb, client_data);
8009acbbeafSnn 
8015240bea1SRod Evans 	rc = (rc != RD_OK) ? rc : rc_brand;
8020ef25df5SEdward Pilatowicz 	return (rc);
8037c478bd9Sstevel@tonic-gate }
804