1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
30*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
31*7c478bd9Sstevel@tonic-gate #include	<proc_service.h>
32*7c478bd9Sstevel@tonic-gate #include	<link.h>
33*7c478bd9Sstevel@tonic-gate #include	<rtld_db.h>
34*7c478bd9Sstevel@tonic-gate #include	<rtld.h>
35*7c478bd9Sstevel@tonic-gate #include	<_rtld_db.h>
36*7c478bd9Sstevel@tonic-gate #include	<msg.h>
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /*
40*7c478bd9Sstevel@tonic-gate  * 64-bit builds are going to compile this module twice, the
41*7c478bd9Sstevel@tonic-gate  * second time with _ELF64 defined.  These defines should make
42*7c478bd9Sstevel@tonic-gate  * all the necessary adjustments to the code.
43*7c478bd9Sstevel@tonic-gate  */
44*7c478bd9Sstevel@tonic-gate #ifdef _LP64
45*7c478bd9Sstevel@tonic-gate #ifdef _ELF64
46*7c478bd9Sstevel@tonic-gate #define	_rd_reset32		_rd_reset64
47*7c478bd9Sstevel@tonic-gate #define	_rd_event_enable32	_rd_event_enable64
48*7c478bd9Sstevel@tonic-gate #define	_rd_event_getmsg32	_rd_event_getmsg64
49*7c478bd9Sstevel@tonic-gate #define	_rd_objpad_enable32	_rd_objpad_enable64
50*7c478bd9Sstevel@tonic-gate #define	_rd_loadobj_iter32	_rd_loadobj_iter64
51*7c478bd9Sstevel@tonic-gate #define	find_dynamic_ent32	find_dynamic_ent64
52*7c478bd9Sstevel@tonic-gate #define	TList			List
53*7c478bd9Sstevel@tonic-gate #define	TListnode		Listnode
54*7c478bd9Sstevel@tonic-gate #else	/* ELF32 */
55*7c478bd9Sstevel@tonic-gate #define	Rt_map			Rt_map32
56*7c478bd9Sstevel@tonic-gate #define	Rtld_db_priv		Rtld_db_priv32
57*7c478bd9Sstevel@tonic-gate #define	TList			List32
58*7c478bd9Sstevel@tonic-gate #define	TListnode		Listnode32
59*7c478bd9Sstevel@tonic-gate #define	Lm_list			Lm_list32
60*7c478bd9Sstevel@tonic-gate #endif	/* _ELF64 */
61*7c478bd9Sstevel@tonic-gate #else	/* _LP64 */
62*7c478bd9Sstevel@tonic-gate #define	TList			List
63*7c478bd9Sstevel@tonic-gate #define	TListnode		Listnode
64*7c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate static rd_err_e
68*7c478bd9Sstevel@tonic-gate validate_rdebug(struct rd_agent *rap)
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
71*7c478bd9Sstevel@tonic-gate 	psaddr_t		db_privp;
72*7c478bd9Sstevel@tonic-gate 	Rtld_db_priv		db_priv;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate 	if (rap->rd_rdebug == 0)
75*7c478bd9Sstevel@tonic-gate 		return (RD_ERR);
76*7c478bd9Sstevel@tonic-gate 	/*
77*7c478bd9Sstevel@tonic-gate 	 * The rtld_db_priv structure contains both the traditional (exposed)
78*7c478bd9Sstevel@tonic-gate 	 * r_debug structure as well as private data only available to
79*7c478bd9Sstevel@tonic-gate 	 * this library.
80*7c478bd9Sstevel@tonic-gate 	 */
81*7c478bd9Sstevel@tonic-gate 	db_privp = rap->rd_rdebug;
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 	/*
84*7c478bd9Sstevel@tonic-gate 	 * Verify that librtld_db & rtld are at the proper revision
85*7c478bd9Sstevel@tonic-gate 	 * levels.
86*7c478bd9Sstevel@tonic-gate 	 */
87*7c478bd9Sstevel@tonic-gate 	if (ps_pread(php, db_privp, (char *)&db_priv,
88*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
89*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
90*7c478bd9Sstevel@tonic-gate 			EC_ADDR(db_privp)));
91*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate 	if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
95*7c478bd9Sstevel@tonic-gate 	    (db_priv.rtd_version > R_RTLDDB_VERSION)) {
96*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
97*7c478bd9Sstevel@tonic-gate 			db_priv.rtd_version, R_RTLDDB_VERSION));
98*7c478bd9Sstevel@tonic-gate 		return (RD_NOCAPAB);
99*7c478bd9Sstevel@tonic-gate 	}
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	/*
102*7c478bd9Sstevel@tonic-gate 	 * Is the image being examined from a core file or not.
103*7c478bd9Sstevel@tonic-gate 	 * If it is a core file then the following write will fail.
104*7c478bd9Sstevel@tonic-gate 	 */
105*7c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, db_privp, (char *)&db_priv,
106*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK)
107*7c478bd9Sstevel@tonic-gate 		rap->rd_flags |= RDF_FL_COREFILE;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	/*
110*7c478bd9Sstevel@tonic-gate 	 * If this *is not* a core file then rtld_db & ld.so.1 are
111*7c478bd9Sstevel@tonic-gate 	 * considered tightly coupled.  If the versions of our private
112*7c478bd9Sstevel@tonic-gate 	 * data structures don't match - fail!
113*7c478bd9Sstevel@tonic-gate 	 */
114*7c478bd9Sstevel@tonic-gate 	if (((rap->rd_flags & RDF_FL_COREFILE) == 0) &&
115*7c478bd9Sstevel@tonic-gate 	    (db_priv.rtd_version != R_RTLDDB_VERSION)) {
116*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
117*7c478bd9Sstevel@tonic-gate 			db_priv.rtd_version, R_RTLDDB_VERSION));
118*7c478bd9Sstevel@tonic-gate 		return (RD_NOCAPAB);
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	rap->rd_rdebugvers = db_priv.rtd_version;
122*7c478bd9Sstevel@tonic-gate 	rap->rd_rtlddbpriv = db_privp;
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
125*7c478bd9Sstevel@tonic-gate 		R_RTLDDB_VERSION, rap->rd_rdebugvers,
126*7c478bd9Sstevel@tonic-gate 		rap->rd_flags & RDF_FL_COREFILE));
127*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate rd_err_e
132*7c478bd9Sstevel@tonic-gate find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
133*7c478bd9Sstevel@tonic-gate 	Xword dyntag, Dyn *dyn)
134*7c478bd9Sstevel@tonic-gate {
135*7c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
136*7c478bd9Sstevel@tonic-gate 	Dyn			d;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	d.d_tag = DT_NULL;
139*7c478bd9Sstevel@tonic-gate 	do {
140*7c478bd9Sstevel@tonic-gate 		if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
141*7c478bd9Sstevel@tonic-gate 		    PS_OK) {
142*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
143*7c478bd9Sstevel@tonic-gate 				EC_ADDR(dynaddr)));
144*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
145*7c478bd9Sstevel@tonic-gate 		}
146*7c478bd9Sstevel@tonic-gate 		dynaddr += sizeof (d);
147*7c478bd9Sstevel@tonic-gate 		if (d.d_tag == dyntag)
148*7c478bd9Sstevel@tonic-gate 			break;
149*7c478bd9Sstevel@tonic-gate 	} while (d.d_tag != DT_NULL);
150*7c478bd9Sstevel@tonic-gate 	if (d.d_tag == dyntag) {
151*7c478bd9Sstevel@tonic-gate 		*dyn = d;
152*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
153*7c478bd9Sstevel@tonic-gate 		    EC_ADDR(d.d_un.d_val)));
154*7c478bd9Sstevel@tonic-gate 		return (RD_OK);
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
157*7c478bd9Sstevel@tonic-gate 	return (RD_DBERR);
158*7c478bd9Sstevel@tonic-gate }
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate rd_err_e
161*7c478bd9Sstevel@tonic-gate _rd_reset32(struct rd_agent *rap)
162*7c478bd9Sstevel@tonic-gate {
163*7c478bd9Sstevel@tonic-gate 	psaddr_t		symaddr;
164*7c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
165*7c478bd9Sstevel@tonic-gate 	const auxv_t		*auxvp = NULL;
166*7c478bd9Sstevel@tonic-gate 	rd_err_e		rc = RD_OK;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	/*
169*7c478bd9Sstevel@tonic-gate 	 * librtld_db attempts three different methods to find
170*7c478bd9Sstevel@tonic-gate 	 * the r_debug structure which is required to
171*7c478bd9Sstevel@tonic-gate 	 * initialize itself.  The methods are:
172*7c478bd9Sstevel@tonic-gate 	 *	method1:
173*7c478bd9Sstevel@tonic-gate 	 *		entirely independent of any text segment
174*7c478bd9Sstevel@tonic-gate 	 *		and relies on the AT_SUN_LDDATA auxvector
175*7c478bd9Sstevel@tonic-gate 	 *		to find the ld.so.1::rdebug structure.
176*7c478bd9Sstevel@tonic-gate 	 *	method2:
177*7c478bd9Sstevel@tonic-gate 	 *		lookup symbols in ld.so.1's symbol table
178*7c478bd9Sstevel@tonic-gate 	 *		to find the r_debug symbol.
179*7c478bd9Sstevel@tonic-gate 	 *	method3:
180*7c478bd9Sstevel@tonic-gate 	 *		(old dbx method) dependent upon the
181*7c478bd9Sstevel@tonic-gate 	 *		text segment/symbol table of the
182*7c478bd9Sstevel@tonic-gate 	 *		executable and not ld.so.1.  We lookup the
183*7c478bd9Sstevel@tonic-gate 	 *		_DYNAMIC symbol in the executable and look for
184*7c478bd9Sstevel@tonic-gate 	 *		the DT_DEBUG entry in the .dynamic table.  This
185*7c478bd9Sstevel@tonic-gate 	 *		points to rdebug.
186*7c478bd9Sstevel@tonic-gate 	 *
187*7c478bd9Sstevel@tonic-gate 	 * If none of that works - we fail.
188*7c478bd9Sstevel@tonic-gate 	 */
189*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * Method1
192*7c478bd9Sstevel@tonic-gate 	 *
193*7c478bd9Sstevel@tonic-gate 	 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
194*7c478bd9Sstevel@tonic-gate 	 */
195*7c478bd9Sstevel@tonic-gate 	if (ps_pauxv(php, &auxvp) != PS_OK) {
196*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
197*7c478bd9Sstevel@tonic-gate 		rc = RD_ERR;
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	rap->rd_rdebug = 0;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (auxvp != NULL) {
203*7c478bd9Sstevel@tonic-gate 		rc = RD_ERR;
204*7c478bd9Sstevel@tonic-gate 		while (auxvp->a_type != AT_NULL) {
205*7c478bd9Sstevel@tonic-gate 			if (auxvp->a_type == AT_SUN_LDDATA) {
206*7c478bd9Sstevel@tonic-gate 				/* LINTED */
207*7c478bd9Sstevel@tonic-gate 				rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
208*7c478bd9Sstevel@tonic-gate 				LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
209*7c478bd9Sstevel@tonic-gate 				    rap->rd_rdebug));
210*7c478bd9Sstevel@tonic-gate 				rc = validate_rdebug(rap);
211*7c478bd9Sstevel@tonic-gate 				break;
212*7c478bd9Sstevel@tonic-gate 			}
213*7c478bd9Sstevel@tonic-gate 			auxvp++;
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	/*
218*7c478bd9Sstevel@tonic-gate 	 * method2 - look for r_rdebug symbol in ld.so.1
219*7c478bd9Sstevel@tonic-gate 	 */
220*7c478bd9Sstevel@tonic-gate 	if (rc != RD_OK) {
221*7c478bd9Sstevel@tonic-gate 		/*
222*7c478bd9Sstevel@tonic-gate 		 * If the AT_SUN_LDDATA auxv vector is not present
223*7c478bd9Sstevel@tonic-gate 		 * fall back on doing a symlookup of
224*7c478bd9Sstevel@tonic-gate 		 * the r_debug symbol.  This is for backward
225*7c478bd9Sstevel@tonic-gate 		 * compatiblity with older OS's
226*7c478bd9Sstevel@tonic-gate 		 */
227*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
228*7c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
229*7c478bd9Sstevel@tonic-gate 		    &symaddr) != PS_OK) {
230*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
231*7c478bd9Sstevel@tonic-gate 				MSG_ORIG(MSG_SYM_DEBUG)));
232*7c478bd9Sstevel@tonic-gate 			rc = RD_DBERR;
233*7c478bd9Sstevel@tonic-gate 		} else {
234*7c478bd9Sstevel@tonic-gate 			rap->rd_rdebug = symaddr;
235*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
236*7c478bd9Sstevel@tonic-gate 				EC_ADDR(symaddr)));
237*7c478bd9Sstevel@tonic-gate 			rc = validate_rdebug(rap);
238*7c478bd9Sstevel@tonic-gate 		}
239*7c478bd9Sstevel@tonic-gate 	}
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/*
243*7c478bd9Sstevel@tonic-gate 	 * method3 - find DT_DEBUG in the executables .dynamic section.
244*7c478bd9Sstevel@tonic-gate 	 */
245*7c478bd9Sstevel@tonic-gate 	if (rc != RD_OK) {
246*7c478bd9Sstevel@tonic-gate 		Dyn	dyn;
247*7c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
248*7c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
249*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
250*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
251*7c478bd9Sstevel@tonic-gate 			return (rc);
252*7c478bd9Sstevel@tonic-gate 		}
253*7c478bd9Sstevel@tonic-gate 		rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
254*7c478bd9Sstevel@tonic-gate 		if (rc != RD_OK) {
255*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
256*7c478bd9Sstevel@tonic-gate 			return (rc);
257*7c478bd9Sstevel@tonic-gate 		}
258*7c478bd9Sstevel@tonic-gate 		rap->rd_rdebug = dyn.d_un.d_ptr;
259*7c478bd9Sstevel@tonic-gate 		rc = validate_rdebug(rap);
260*7c478bd9Sstevel@tonic-gate 		if (rc != RD_OK) {
261*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
262*7c478bd9Sstevel@tonic-gate 			return (rc);
263*7c478bd9Sstevel@tonic-gate 		}
264*7c478bd9Sstevel@tonic-gate 	}
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
267*7c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
268*7c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
269*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
270*7c478bd9Sstevel@tonic-gate 				MSG_ORIG(MSG_SYM_PREINIT)));
271*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
272*7c478bd9Sstevel@tonic-gate 		}
273*7c478bd9Sstevel@tonic-gate 		rap->rd_preinit = symaddr;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
276*7c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
277*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
278*7c478bd9Sstevel@tonic-gate 				MSG_ORIG(MSG_SYM_POSTINIT)));
279*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 		rap->rd_postinit = symaddr;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
284*7c478bd9Sstevel@tonic-gate 		    MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
285*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
286*7c478bd9Sstevel@tonic-gate 				MSG_ORIG(MSG_SYM_DLACT)));
287*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
288*7c478bd9Sstevel@tonic-gate 		}
289*7c478bd9Sstevel@tonic-gate 		rap->rd_dlact = symaddr;
290*7c478bd9Sstevel@tonic-gate 		rap->rd_tbinder = 0;
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate rd_err_e
298*7c478bd9Sstevel@tonic-gate _rd_event_enable32(rd_agent_t *rap, int onoff)
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
301*7c478bd9Sstevel@tonic-gate 	Rtld_db_priv		rdb;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
304*7c478bd9Sstevel@tonic-gate 	/*
305*7c478bd9Sstevel@tonic-gate 	 * Tell the debugged process that debugging is occuring
306*7c478bd9Sstevel@tonic-gate 	 * This will enable the storing of event messages so that
307*7c478bd9Sstevel@tonic-gate 	 * the can be gathered by the debugger.
308*7c478bd9Sstevel@tonic-gate 	 */
309*7c478bd9Sstevel@tonic-gate 	if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
310*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
311*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
312*7c478bd9Sstevel@tonic-gate 		    EC_ADDR((uintptr_t)&rdb)));
313*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
314*7c478bd9Sstevel@tonic-gate 	}
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	if (onoff)
317*7c478bd9Sstevel@tonic-gate 		rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
318*7c478bd9Sstevel@tonic-gate 	else
319*7c478bd9Sstevel@tonic-gate 		rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
322*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
323*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
324*7c478bd9Sstevel@tonic-gate 		    EC_ADDR((uintptr_t)&rdb)));
325*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate rd_err_e
333*7c478bd9Sstevel@tonic-gate _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
334*7c478bd9Sstevel@tonic-gate {
335*7c478bd9Sstevel@tonic-gate 	Rtld_db_priv	rdb;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
338*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
339*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
340*7c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rdebug)));
341*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
342*7c478bd9Sstevel@tonic-gate 	}
343*7c478bd9Sstevel@tonic-gate 	emsg->type = rdb.rtd_rdebug.r_rdevent;
344*7c478bd9Sstevel@tonic-gate 	if (emsg->type == RD_DLACTIVITY) {
345*7c478bd9Sstevel@tonic-gate 		switch (rdb.rtd_rdebug.r_state) {
346*7c478bd9Sstevel@tonic-gate 			case RT_CONSISTENT:
347*7c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_CONSISTENT;
348*7c478bd9Sstevel@tonic-gate 				break;
349*7c478bd9Sstevel@tonic-gate 			case RT_ADD:
350*7c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_ADD;
351*7c478bd9Sstevel@tonic-gate 				break;
352*7c478bd9Sstevel@tonic-gate 			case RT_DELETE:
353*7c478bd9Sstevel@tonic-gate 				emsg->u.state = RD_DELETE;
354*7c478bd9Sstevel@tonic-gate 				break;
355*7c478bd9Sstevel@tonic-gate 		}
356*7c478bd9Sstevel@tonic-gate 	} else
357*7c478bd9Sstevel@tonic-gate 		emsg->u.state = RD_NOSTATE;
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
360*7c478bd9Sstevel@tonic-gate 		emsg->type, emsg->u.state));
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
363*7c478bd9Sstevel@tonic-gate }
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate rd_err_e
367*7c478bd9Sstevel@tonic-gate _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
368*7c478bd9Sstevel@tonic-gate {
369*7c478bd9Sstevel@tonic-gate 	Rtld_db_priv		db_priv;
370*7c478bd9Sstevel@tonic-gate 	struct ps_prochandle	*php = rap->rd_psp;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
375*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
376*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
377*7c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
378*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
379*7c478bd9Sstevel@tonic-gate 	}
380*7c478bd9Sstevel@tonic-gate #if	defined(_LP64) && !defined(_ELF64)
381*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
382*7c478bd9Sstevel@tonic-gate 	db_priv.rtd_objpad = (uint32_t)padsize;
383*7c478bd9Sstevel@tonic-gate #else
384*7c478bd9Sstevel@tonic-gate 	db_priv.rtd_objpad = padsize;
385*7c478bd9Sstevel@tonic-gate #endif
386*7c478bd9Sstevel@tonic-gate 	if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
387*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
388*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
389*7c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
390*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate static rd_err_e
399*7c478bd9Sstevel@tonic-gate iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
400*7c478bd9Sstevel@tonic-gate 	rl_iter_f *cb, void *client_data, uint_t *abort_iter)
401*7c478bd9Sstevel@tonic-gate {
402*7c478bd9Sstevel@tonic-gate 	while (lmaddr) {
403*7c478bd9Sstevel@tonic-gate 		Rt_map		rmap;
404*7c478bd9Sstevel@tonic-gate 		rd_loadobj_t	lobj;
405*7c478bd9Sstevel@tonic-gate 		int		i;
406*7c478bd9Sstevel@tonic-gate 		ulong_t		off;
407*7c478bd9Sstevel@tonic-gate 		Ehdr		ehdr;
408*7c478bd9Sstevel@tonic-gate 		Phdr		phdr;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 		if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
411*7c478bd9Sstevel@tonic-gate 		    sizeof (Rt_map)) != PS_OK) {
412*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
413*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
414*7c478bd9Sstevel@tonic-gate 		}
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 		/*
417*7c478bd9Sstevel@tonic-gate 		 * As of 'VERSION5' we only report objects
418*7c478bd9Sstevel@tonic-gate 		 * which have been fully relocated.  While the maps
419*7c478bd9Sstevel@tonic-gate 		 * might be in a consistent state - if a object hasn't
420*7c478bd9Sstevel@tonic-gate 		 * been relocated - it's not really ready for the debuggers
421*7c478bd9Sstevel@tonic-gate 		 * to examine.  This is mostly due to the fact that we
422*7c478bd9Sstevel@tonic-gate 		 * might still be mucking with the text-segment, if
423*7c478bd9Sstevel@tonic-gate 		 * we are - we could conflict with any break-points
424*7c478bd9Sstevel@tonic-gate 		 * the debuggers might have set.
425*7c478bd9Sstevel@tonic-gate 		 */
426*7c478bd9Sstevel@tonic-gate 		if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
427*7c478bd9Sstevel@tonic-gate 			if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
428*7c478bd9Sstevel@tonic-gate 				lmaddr = (psaddr_t)NEXT(&rmap);
429*7c478bd9Sstevel@tonic-gate 				continue;
430*7c478bd9Sstevel@tonic-gate 			}
431*7c478bd9Sstevel@tonic-gate 		}
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 		lobj.rl_base = (psaddr_t)ADDR(&rmap);
434*7c478bd9Sstevel@tonic-gate 		lobj.rl_lmident = ident;
435*7c478bd9Sstevel@tonic-gate 		lobj.rl_flags = 0;
436*7c478bd9Sstevel@tonic-gate 		lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 		/*
439*7c478bd9Sstevel@tonic-gate 		 * refnameaddr is only valid from a core file
440*7c478bd9Sstevel@tonic-gate 		 * which is VERSION3 or greater.
441*7c478bd9Sstevel@tonic-gate 		 */
442*7c478bd9Sstevel@tonic-gate 		if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
443*7c478bd9Sstevel@tonic-gate 			lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
444*7c478bd9Sstevel@tonic-gate 			lobj.rl_bend = 0;
445*7c478bd9Sstevel@tonic-gate 			lobj.rl_padstart = 0;
446*7c478bd9Sstevel@tonic-gate 			lobj.rl_padend = 0;
447*7c478bd9Sstevel@tonic-gate 		} else {
448*7c478bd9Sstevel@tonic-gate 			lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
449*7c478bd9Sstevel@tonic-gate 			lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
450*7c478bd9Sstevel@tonic-gate 			lobj.rl_padstart = PADSTART(&rmap);
451*7c478bd9Sstevel@tonic-gate 			lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION2)
456*7c478bd9Sstevel@tonic-gate 			if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
457*7c478bd9Sstevel@tonic-gate 				lobj.rl_flags |= RD_FLG_MEM_OBJECT;
458*7c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION2) {
459*7c478bd9Sstevel@tonic-gate 			lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
460*7c478bd9Sstevel@tonic-gate 		}
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 		if (rtld_db_version >= RD_VERSION4)
463*7c478bd9Sstevel@tonic-gate 			lobj.rl_tlsmodid = TLSMODID(&rmap);
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 		/*
466*7c478bd9Sstevel@tonic-gate 		 * Look for beginning of data segment.
467*7c478bd9Sstevel@tonic-gate 		 *
468*7c478bd9Sstevel@tonic-gate 		 * NOTE: the data segment can only be found for full
469*7c478bd9Sstevel@tonic-gate 		 *	processes and not from core images.
470*7c478bd9Sstevel@tonic-gate 		 */
471*7c478bd9Sstevel@tonic-gate 		lobj.rl_data_base = 0;
472*7c478bd9Sstevel@tonic-gate 		if (rap->rd_flags & RDF_FL_COREFILE)
473*7c478bd9Sstevel@tonic-gate 			lobj.rl_data_base = 0;
474*7c478bd9Sstevel@tonic-gate 		else {
475*7c478bd9Sstevel@tonic-gate 			off = ADDR(&rmap);
476*7c478bd9Sstevel@tonic-gate 			if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
477*7c478bd9Sstevel@tonic-gate 			    sizeof (Ehdr)) != PS_OK) {
478*7c478bd9Sstevel@tonic-gate 				LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
479*7c478bd9Sstevel@tonic-gate 				return (RD_DBERR);
480*7c478bd9Sstevel@tonic-gate 			}
481*7c478bd9Sstevel@tonic-gate 			off += sizeof (Ehdr);
482*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < ehdr.e_phnum; i++) {
483*7c478bd9Sstevel@tonic-gate 				if (ps_pread(rap->rd_psp, off, (char *)&phdr,
484*7c478bd9Sstevel@tonic-gate 				    sizeof (Phdr)) != PS_OK) {
485*7c478bd9Sstevel@tonic-gate 					LOG(ps_plog(MSG_ORIG(
486*7c478bd9Sstevel@tonic-gate 					    MSG_DB_LKMAPFAIL)));
487*7c478bd9Sstevel@tonic-gate 					return (RD_DBERR);
488*7c478bd9Sstevel@tonic-gate 				}
489*7c478bd9Sstevel@tonic-gate 				if ((phdr.p_type == PT_LOAD) &&
490*7c478bd9Sstevel@tonic-gate 				    (phdr.p_flags & PF_W)) {
491*7c478bd9Sstevel@tonic-gate 					lobj.rl_data_base = phdr.p_vaddr;
492*7c478bd9Sstevel@tonic-gate 					if (ehdr.e_type == ET_DYN)
493*7c478bd9Sstevel@tonic-gate 						lobj.rl_data_base +=
494*7c478bd9Sstevel@tonic-gate 							ADDR(&rmap);
495*7c478bd9Sstevel@tonic-gate 					break;
496*7c478bd9Sstevel@tonic-gate 				}
497*7c478bd9Sstevel@tonic-gate 				off += ehdr.e_phentsize;
498*7c478bd9Sstevel@tonic-gate 			}
499*7c478bd9Sstevel@tonic-gate 		}
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 		/*
503*7c478bd9Sstevel@tonic-gate 		 * When we transfer control to the client we free the
504*7c478bd9Sstevel@tonic-gate 		 * lock and re-atain it after we've returned from the
505*7c478bd9Sstevel@tonic-gate 		 * client.  This is to avoid any deadlock situations.
506*7c478bd9Sstevel@tonic-gate 		 */
507*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
508*7c478bd9Sstevel@tonic-gate 			EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
509*7c478bd9Sstevel@tonic-gate 		RDAGUNLOCK(rap);
510*7c478bd9Sstevel@tonic-gate 		if ((*cb)(&lobj, client_data) == 0) {
511*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
512*7c478bd9Sstevel@tonic-gate 			RDAGLOCK(rap);
513*7c478bd9Sstevel@tonic-gate 			*abort_iter = 1;
514*7c478bd9Sstevel@tonic-gate 			break;
515*7c478bd9Sstevel@tonic-gate 		}
516*7c478bd9Sstevel@tonic-gate 		RDAGLOCK(rap);
517*7c478bd9Sstevel@tonic-gate 		lmaddr = (psaddr_t)NEXT(&rmap);
518*7c478bd9Sstevel@tonic-gate 	}
519*7c478bd9Sstevel@tonic-gate 	return (RD_OK);
520*7c478bd9Sstevel@tonic-gate }
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate rd_err_e
524*7c478bd9Sstevel@tonic-gate _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
525*7c478bd9Sstevel@tonic-gate {
526*7c478bd9Sstevel@tonic-gate 	Rtld_db_priv	db_priv;
527*7c478bd9Sstevel@tonic-gate 	TList		list;
528*7c478bd9Sstevel@tonic-gate 	TListnode	lnode;
529*7c478bd9Sstevel@tonic-gate 	Addr		lnp;
530*7c478bd9Sstevel@tonic-gate 	unsigned long	ident;
531*7c478bd9Sstevel@tonic-gate 	rd_err_e	rc;
532*7c478bd9Sstevel@tonic-gate 	uint_t		abort_iter = 0;
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
535*7c478bd9Sstevel@tonic-gate 		client_data));
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
538*7c478bd9Sstevel@tonic-gate 	    sizeof (Rtld_db_priv)) != PS_OK) {
539*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
540*7c478bd9Sstevel@tonic-gate 		    EC_ADDR(rap->rd_rtlddbpriv)));
541*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	if (db_priv.rtd_dynlmlst == 0) {
545*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
546*7c478bd9Sstevel@tonic-gate 			EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
547*7c478bd9Sstevel@tonic-gate 		return (RD_NOMAPS);
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list,
551*7c478bd9Sstevel@tonic-gate 	    sizeof (TList)) != PS_OK) {
552*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
553*7c478bd9Sstevel@tonic-gate 			EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
554*7c478bd9Sstevel@tonic-gate 		return (RD_DBERR);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	if (list.head == 0) {
558*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
559*7c478bd9Sstevel@tonic-gate 			EC_ADDR((uintptr_t)list.head)));
560*7c478bd9Sstevel@tonic-gate 		return (RD_NOMAPS);
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 	if (cb == 0) {
565*7c478bd9Sstevel@tonic-gate 		LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
566*7c478bd9Sstevel@tonic-gate 		return (RD_ERR);
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
570*7c478bd9Sstevel@tonic-gate 		Lm_list	lml;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 		/*
573*7c478bd9Sstevel@tonic-gate 		 * Iterate through the List of Lm_list's.
574*7c478bd9Sstevel@tonic-gate 		 */
575*7c478bd9Sstevel@tonic-gate 		if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
576*7c478bd9Sstevel@tonic-gate 		    sizeof (TListnode)) != PS_OK) {
577*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
578*7c478bd9Sstevel@tonic-gate 				EC_ADDR(lnp)));
579*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
580*7c478bd9Sstevel@tonic-gate 		}
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml,
583*7c478bd9Sstevel@tonic-gate 		    sizeof (Lm_list)) != PS_OK) {
584*7c478bd9Sstevel@tonic-gate 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
585*7c478bd9Sstevel@tonic-gate 				EC_ADDR((uintptr_t)lnode.data)));
586*7c478bd9Sstevel@tonic-gate 			return (RD_DBERR);
587*7c478bd9Sstevel@tonic-gate 		}
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 		/*
590*7c478bd9Sstevel@tonic-gate 		 * Determine IDENT of current LM_LIST
591*7c478bd9Sstevel@tonic-gate 		 */
592*7c478bd9Sstevel@tonic-gate 		if (lml.lm_flags & LML_FLG_BASELM)
593*7c478bd9Sstevel@tonic-gate 			ident = LM_ID_BASE;
594*7c478bd9Sstevel@tonic-gate 		else if (lml.lm_flags & LML_FLG_RTLDLM)
595*7c478bd9Sstevel@tonic-gate 			ident = LM_ID_LDSO;
596*7c478bd9Sstevel@tonic-gate 		else
597*7c478bd9Sstevel@tonic-gate 			ident = (unsigned long)lnode.data;
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 		if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
600*7c478bd9Sstevel@tonic-gate 		    cb, client_data, &abort_iter)) != RD_OK) {
601*7c478bd9Sstevel@tonic-gate 			return (rc);
602*7c478bd9Sstevel@tonic-gate 		}
603*7c478bd9Sstevel@tonic-gate 		if (abort_iter)
604*7c478bd9Sstevel@tonic-gate 			break;
605*7c478bd9Sstevel@tonic-gate 	}
606*7c478bd9Sstevel@tonic-gate 	return (rc);
607*7c478bd9Sstevel@tonic-gate }
608