xref: /illumos-gate/usr/src/cmd/sgs/librtld_db/common/rd_elf.c (revision 66e150d7d3c0cb2de3c45c74612784ffd3e73de6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include	<stdlib.h>
29 #include	<stdio.h>
30 #include	<proc_service.h>
31 #include	<link.h>
32 #include	<rtld_db.h>
33 #include	<rtld.h>
34 #include	<_rtld_db.h>
35 #include	<msg.h>
36 #include	<limits.h>
37 #include	<string.h>
38 #include	<sys/param.h>
39 
40 /*
41  * 64-bit builds are going to compile this module twice, the
42  * second time with _ELF64 defined.  These defines should make
43  * all the necessary adjustments to the code.
44  */
45 #ifdef _LP64
46 #ifdef _ELF64
47 #define	_rd_event_enable32	_rd_event_enable64
48 #define	_rd_event_getmsg32	_rd_event_getmsg64
49 #define	_rd_get_dyns32		_rd_get_dyns64
50 #define	_rd_get_ehdr32		_rd_get_ehdr64
51 #define	_rd_objpad_enable32	_rd_objpad_enable64
52 #define	_rd_loadobj_iter32	_rd_loadobj_iter64
53 #define	_rd_reset32		_rd_reset64
54 #define	find_dynamic_ent32	find_dynamic_ent64
55 #define	validate_rdebug32	validate_rdebug64
56 #define	TList			List
57 #define	TListnode		Listnode
58 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_64
59 #else	/* ELF32 */
60 #define	Rt_map			Rt_map32
61 #define	Rtld_db_priv		Rtld_db_priv32
62 #define	TList			List32
63 #define	TListnode		Listnode32
64 #define	Lm_list			Lm_list32
65 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
66 #endif	/* _ELF64 */
67 #else	/* _LP64 */
68 #define	TList			List
69 #define	TListnode		Listnode
70 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
71 #endif	/* _LP64 */
72 
73 /*
74  * BrandZ added ps_pbrandname().  Many debuggers that link directly
75  * against librtld_db.so may not implement this interface.  Hence
76  * we won't call the function directly, instead we'll try to look it
77  * up using the linker first and only invoke it if we find it.
78  */
79 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
80     char *, size_t);
81 
82 rd_err_e
83 validate_rdebug32(struct rd_agent *rap)
84 {
85 	struct ps_prochandle	*php = rap->rd_psp;
86 	psaddr_t		db_privp;
87 	Rtld_db_priv		db_priv;
88 
89 	if (rap->rd_rdebug == 0)
90 		return (RD_ERR);
91 	/*
92 	 * The rtld_db_priv structure contains both the traditional (exposed)
93 	 * r_debug structure as well as private data only available to
94 	 * this library.
95 	 */
96 	db_privp = rap->rd_rdebug;
97 
98 	/*
99 	 * Verify that librtld_db & rtld are at the proper revision
100 	 * levels.
101 	 */
102 	if (ps_pread(php, db_privp, (char *)&db_priv,
103 	    sizeof (Rtld_db_priv)) != PS_OK) {
104 		LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
105 		    EC_ADDR(db_privp)));
106 		return (RD_DBERR);
107 	}
108 
109 	if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
110 	    (db_priv.rtd_version > R_RTLDDB_VERSION)) {
111 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
112 		    db_priv.rtd_version, R_RTLDDB_VERSION));
113 		return (RD_NOCAPAB);
114 	}
115 
116 	/*
117 	 * Is the image being examined from a core file or not.
118 	 * If it is a core file then the following write will fail.
119 	 */
120 	if (ps_pwrite(php, db_privp, (char *)&db_priv,
121 	    sizeof (Rtld_db_priv)) != PS_OK)
122 		rap->rd_flags |= RDF_FL_COREFILE;
123 
124 	/*
125 	 * If this *is not* a core file then rtld_db & ld.so.1 are
126 	 * considered tightly coupled.  If the versions of our private
127 	 * data structures don't match - fail!
128 	 */
129 	if (((rap->rd_flags & RDF_FL_COREFILE) == 0) &&
130 	    (db_priv.rtd_version != R_RTLDDB_VERSION)) {
131 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
132 		    db_priv.rtd_version, R_RTLDDB_VERSION));
133 		return (RD_NOCAPAB);
134 	}
135 
136 	rap->rd_rdebugvers = db_priv.rtd_version;
137 	rap->rd_rtlddbpriv = db_privp;
138 
139 	LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
140 	    R_RTLDDB_VERSION, rap->rd_rdebugvers,
141 	    rap->rd_flags & RDF_FL_COREFILE));
142 	return (RD_OK);
143 }
144 
145 
146 rd_err_e
147 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
148 	Xword dyntag, Dyn *dyn)
149 {
150 	struct ps_prochandle	*php = rap->rd_psp;
151 	Dyn			d;
152 
153 	d.d_tag = DT_NULL;
154 	do {
155 		if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
156 		    PS_OK) {
157 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
158 			    EC_ADDR(dynaddr)));
159 			return (RD_DBERR);
160 		}
161 		dynaddr += sizeof (d);
162 		if (d.d_tag == dyntag)
163 			break;
164 	} while (d.d_tag != DT_NULL);
165 	if (d.d_tag == dyntag) {
166 		*dyn = d;
167 		LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
168 		    EC_ADDR(d.d_un.d_val)));
169 		return (RD_OK);
170 	}
171 	LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
172 	return (RD_DBERR);
173 }
174 
175 extern char rtld_db_helper_path[MAXPATHLEN];
176 
177 rd_err_e
178 _rd_reset32(struct rd_agent *rap)
179 {
180 	psaddr_t		symaddr;
181 	struct ps_prochandle	*php = rap->rd_psp;
182 	const auxv_t		*auxvp = NULL;
183 	rd_err_e		rc = RD_OK;
184 	char			brandname[MAXPATHLEN];
185 	char			brandlib[MAXPATHLEN];
186 	ps_pbrandname_fp_t	ps_pbrandname;
187 
188 	/*
189 	 * librtld_db attempts three different methods to find
190 	 * the r_debug structure which is required to
191 	 * initialize itself.  The methods are:
192 	 *	method1:
193 	 *		entirely independent of any text segment
194 	 *		and relies on the AT_SUN_LDDATA auxvector
195 	 *		to find the ld.so.1::rdebug structure.
196 	 *	method2:
197 	 *		lookup symbols in ld.so.1's symbol table
198 	 *		to find the r_debug symbol.
199 	 *	method3:
200 	 *		(old dbx method) dependent upon the
201 	 *		text segment/symbol table of the
202 	 *		executable and not ld.so.1.  We lookup the
203 	 *		_DYNAMIC symbol in the executable and look for
204 	 *		the DT_DEBUG entry in the .dynamic table.  This
205 	 *		points to rdebug.
206 	 *
207 	 * If none of that works - we fail.
208 	 */
209 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
210 	/*
211 	 * Method1
212 	 *
213 	 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
214 	 */
215 
216 	if (ps_pauxv(php, &auxvp) != PS_OK) {
217 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
218 		rc = RD_ERR;
219 	}
220 
221 	rap->rd_rdebug = 0;
222 
223 	if (auxvp != NULL) {
224 		rc = RD_ERR;
225 		while (auxvp->a_type != AT_NULL) {
226 			if (auxvp->a_type == AT_SUN_LDDATA) {
227 				/* LINTED */
228 				rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
229 				LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
230 				    rap->rd_rdebug));
231 				rc = validate_rdebug32(rap);
232 				break;
233 			}
234 			auxvp++;
235 		}
236 	}
237 
238 	/*
239 	 * method2 - look for r_rdebug symbol in ld.so.1
240 	 */
241 	if (rc != RD_OK) {
242 		/*
243 		 * If the AT_SUN_LDDATA auxv vector is not present
244 		 * fall back on doing a symlookup of
245 		 * the r_debug symbol.  This is for backward
246 		 * compatiblity with older OS's
247 		 */
248 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
249 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
250 		    &symaddr) != PS_OK) {
251 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
252 			    MSG_ORIG(MSG_SYM_DEBUG)));
253 			rc = RD_DBERR;
254 		} else {
255 			rap->rd_rdebug = symaddr;
256 			LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
257 			    EC_ADDR(symaddr)));
258 			rc = validate_rdebug32(rap);
259 		}
260 	}
261 
262 
263 	/*
264 	 * method3 - find DT_DEBUG in the executables .dynamic section.
265 	 */
266 	if (rc != RD_OK) {
267 		Dyn	dyn;
268 		if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
269 		    MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
270 			LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
271 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
272 			return (rc);
273 		}
274 		rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
275 		if (rc != RD_OK) {
276 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
277 			return (rc);
278 		}
279 		rap->rd_rdebug = dyn.d_un.d_ptr;
280 		rc = validate_rdebug32(rap);
281 		if (rc != RD_OK) {
282 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
283 			return (rc);
284 		}
285 	}
286 
287 	/*
288 	 * If we are debugging a branded executable, load the appropriate
289 	 * helper library, and call its initialization routine.  Being unable
290 	 * to load the helper library is not a critical error.  (Hopefully
291 	 * we'll still be able to access some objects in the target.)
292 	 */
293 	ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
294 	while ((ps_pbrandname != NULL) &&
295 	    (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
296 		const char *isa = "";
297 
298 #ifdef _LP64
299 		isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
300 #endif /* _LP64 */
301 
302 		if (rtld_db_helper_path[0] != '\0')
303 			(void) snprintf(brandlib, MAXPATHLEN,
304 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
305 			    rtld_db_helper_path,
306 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
307 			    brandname);
308 		else
309 			(void) snprintf(brandlib, MAXPATHLEN,
310 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH),
311 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
312 			    brandname);
313 
314 		rap->rd_helper.rh_dlhandle = dlopen(brandlib,
315 		    RTLD_LAZY | RTLD_LOCAL);
316 		if (rap->rd_helper.rh_dlhandle == NULL) {
317 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
318 			    brandlib));
319 			break;
320 		}
321 
322 		rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
323 		    MSG_ORIG(MSG_SYM_BRANDOPS));
324 		if (rap->rd_helper.rh_ops == NULL) {
325 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
326 			    brandlib));
327 			(void) dlclose(rap->rd_helper.rh_dlhandle);
328 			rap->rd_helper.rh_dlhandle = NULL;
329 			break;
330 		}
331 
332 		rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
333 		    php);
334 		if (rap->rd_helper.rh_data == NULL) {
335 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
336 			(void) dlclose(rap->rd_helper.rh_dlhandle);
337 			rap->rd_helper.rh_dlhandle = NULL;
338 			rap->rd_helper.rh_ops = NULL;
339 			break;
340 		}
341 
342 		LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
343 		break;
344 
345 		/* NOTREACHED */
346 	}
347 
348 	if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
349 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
350 		    MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
351 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
352 			    MSG_ORIG(MSG_SYM_PREINIT)));
353 			return (RD_DBERR);
354 		}
355 		rap->rd_preinit = symaddr;
356 
357 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
358 		    MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
359 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
360 			    MSG_ORIG(MSG_SYM_POSTINIT)));
361 			return (RD_DBERR);
362 		}
363 		rap->rd_postinit = symaddr;
364 
365 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
366 		    MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
367 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
368 			    MSG_ORIG(MSG_SYM_DLACT)));
369 			return (RD_DBERR);
370 		}
371 		rap->rd_dlact = symaddr;
372 		rap->rd_tbinder = 0;
373 	}
374 
375 	return (RD_OK);
376 }
377 
378 rd_err_e
379 _rd_get_ehdr32(struct rd_agent *rap,
380     psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
381 {
382 	struct ps_prochandle	*php = rap->rd_psp;
383 	Shdr			shdr;
384 
385 	if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
386 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
387 		return (RD_ERR);
388 	}
389 	if (phnum == NULL)
390 		return (RD_OK);
391 
392 	if (ehdr->e_phnum != PN_XNUM) {
393 		*phnum = ehdr->e_phnum;
394 		return (RD_OK);
395 	}
396 
397 	/* deal with elf extended program headers */
398 	if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
399 		return (RD_ERR);
400 
401 	addr += ehdr->e_shoff;
402 	if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
403 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
404 		return (RD_ERR);
405 	}
406 
407 	if (shdr.sh_info == 0)
408 		return (RD_ERR);
409 
410 	*phnum = shdr.sh_info;
411 	return (RD_OK);
412 }
413 
414 rd_err_e
415 _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
416 {
417 	struct ps_prochandle	*php = rap->rd_psp;
418 	rd_err_e		err;
419 	uint_t			phnum;
420 	Ehdr			ehdr;
421 	Phdr			phdr;
422 	Dyn			*dynp;
423 	int			i;
424 
425 	/* We only need to muck with dyn elements for ET_DYN objects */
426 	if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
427 		return (err);
428 
429 	for (i = 0; i < phnum; i++) {
430 		psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
431 		if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
432 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
433 			return (RD_ERR);
434 		}
435 		if (phdr.p_type == PT_DYNAMIC)
436 			break;
437 	}
438 	if (i == phnum)
439 		return (RD_ERR);
440 
441 	if ((dynp = malloc(phdr.p_filesz)) == NULL)
442 		return (RD_ERR);
443 	if (ehdr.e_type == ET_DYN)
444 		phdr.p_vaddr += addr;
445 	if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
446 		free(dynp);
447 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
448 		    EC_ADDR(phdr.p_vaddr)));
449 		return (RD_ERR);
450 	}
451 
452 	*dynpp = dynp;
453 	if (dynpp_sz != NULL)
454 		*dynpp_sz = phdr.p_filesz;
455 	return (RD_OK);
456 }
457 
458 rd_err_e
459 _rd_event_enable32(rd_agent_t *rap, int onoff)
460 {
461 	struct ps_prochandle	*php = rap->rd_psp;
462 	Rtld_db_priv		rdb;
463 
464 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
465 	/*
466 	 * Tell the debugged process that debugging is occuring
467 	 * This will enable the storing of event messages so that
468 	 * the can be gathered by the debugger.
469 	 */
470 	if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
471 	    sizeof (Rtld_db_priv)) != PS_OK) {
472 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
473 		    EC_ADDR((uintptr_t)&rdb)));
474 		return (RD_DBERR);
475 	}
476 
477 	if (onoff)
478 		rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
479 	else
480 		rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
481 
482 	if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
483 	    sizeof (Rtld_db_priv)) != PS_OK) {
484 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
485 		    EC_ADDR((uintptr_t)&rdb)));
486 		return (RD_DBERR);
487 	}
488 
489 	return (RD_OK);
490 }
491 
492 
493 rd_err_e
494 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
495 {
496 	Rtld_db_priv	rdb;
497 
498 	if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
499 	    sizeof (Rtld_db_priv)) != PS_OK) {
500 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
501 		    EC_ADDR(rap->rd_rdebug)));
502 		return (RD_DBERR);
503 	}
504 	emsg->type = rdb.rtd_rdebug.r_rdevent;
505 	if (emsg->type == RD_DLACTIVITY) {
506 		switch (rdb.rtd_rdebug.r_state) {
507 			case RT_CONSISTENT:
508 				emsg->u.state = RD_CONSISTENT;
509 				break;
510 			case RT_ADD:
511 				emsg->u.state = RD_ADD;
512 				break;
513 			case RT_DELETE:
514 				emsg->u.state = RD_DELETE;
515 				break;
516 		}
517 	} else
518 		emsg->u.state = RD_NOSTATE;
519 
520 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
521 	    emsg->type, emsg->u.state));
522 
523 	return (RD_OK);
524 }
525 
526 
527 rd_err_e
528 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
529 {
530 	Rtld_db_priv		db_priv;
531 	struct ps_prochandle	*php = rap->rd_psp;
532 
533 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
534 
535 	if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
536 	    sizeof (Rtld_db_priv)) != PS_OK) {
537 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
538 		    EC_ADDR(rap->rd_rtlddbpriv)));
539 		return (RD_DBERR);
540 	}
541 #if	defined(_LP64) && !defined(_ELF64)
542 	/*LINTED*/
543 	db_priv.rtd_objpad = (uint32_t)padsize;
544 #else
545 	db_priv.rtd_objpad = padsize;
546 #endif
547 	if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
548 	    sizeof (Rtld_db_priv)) != PS_OK) {
549 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
550 		    EC_ADDR(rap->rd_rtlddbpriv)));
551 		return (RD_DBERR);
552 	}
553 	return (RD_OK);
554 }
555 
556 static rd_err_e
557 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
558 	rl_iter_f *cb, void *client_data, uint_t *abort_iter)
559 {
560 	while (lmaddr) {
561 		Rt_map		rmap;
562 		rd_loadobj_t	lobj;
563 		int		i;
564 		ulong_t		off;
565 		Ehdr		ehdr;
566 		Phdr		phdr;
567 
568 		if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
569 		    sizeof (Rt_map)) != PS_OK) {
570 			LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
571 			return (RD_DBERR);
572 		}
573 
574 		/*
575 		 * As of 'VERSION5' we only report objects
576 		 * which have been fully relocated.  While the maps
577 		 * might be in a consistent state - if a object hasn't
578 		 * been relocated - it's not really ready for the debuggers
579 		 * to examine.  This is mostly due to the fact that we
580 		 * might still be mucking with the text-segment, if
581 		 * we are - we could conflict with any break-points
582 		 * the debuggers might have set.
583 		 */
584 		if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
585 			if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
586 				lmaddr = (psaddr_t)NEXT(&rmap);
587 				continue;
588 			}
589 		}
590 
591 		lobj.rl_base = (psaddr_t)ADDR(&rmap);
592 		lobj.rl_flags = 0;
593 		lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
594 		if ((rap->rd_helper.rh_ops != NULL) &&
595 		    (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
596 			lobj.rl_lmident =
597 			    rap->rd_helper.rh_ops->rho_lmid;
598 		else
599 			lobj.rl_lmident = ident;
600 
601 		/*
602 		 * refnameaddr is only valid from a core file
603 		 * which is VERSION3 or greater.
604 		 */
605 		if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
606 			lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
607 			lobj.rl_bend = 0;
608 			lobj.rl_padstart = 0;
609 			lobj.rl_padend = 0;
610 		} else {
611 			lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
612 			lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
613 			lobj.rl_padstart = PADSTART(&rmap);
614 			lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
615 
616 		}
617 
618 		if (rtld_db_version >= RD_VERSION2)
619 			if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
620 				lobj.rl_flags |= RD_FLG_MEM_OBJECT;
621 		if (rtld_db_version >= RD_VERSION2) {
622 			lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
623 		}
624 
625 		if (rtld_db_version >= RD_VERSION4)
626 			lobj.rl_tlsmodid = TLSMODID(&rmap);
627 
628 		/*
629 		 * Look for beginning of data segment.
630 		 *
631 		 * NOTE: the data segment can only be found for full
632 		 *	processes and not from core images.
633 		 */
634 		lobj.rl_data_base = 0;
635 		if (rap->rd_flags & RDF_FL_COREFILE)
636 			lobj.rl_data_base = 0;
637 		else {
638 			off = ADDR(&rmap);
639 			if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
640 			    sizeof (Ehdr)) != PS_OK) {
641 				LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
642 				return (RD_DBERR);
643 			}
644 			off += sizeof (Ehdr);
645 			for (i = 0; i < ehdr.e_phnum; i++) {
646 				if (ps_pread(rap->rd_psp, off, (char *)&phdr,
647 				    sizeof (Phdr)) != PS_OK) {
648 					LOG(ps_plog(MSG_ORIG(
649 					    MSG_DB_LKMAPFAIL)));
650 					return (RD_DBERR);
651 				}
652 				if ((phdr.p_type == PT_LOAD) &&
653 				    (phdr.p_flags & PF_W)) {
654 					lobj.rl_data_base = phdr.p_vaddr;
655 					if (ehdr.e_type == ET_DYN)
656 						lobj.rl_data_base +=
657 						    ADDR(&rmap);
658 					break;
659 				}
660 				off += ehdr.e_phentsize;
661 			}
662 		}
663 
664 		/*
665 		 * When we transfer control to the client we free the
666 		 * lock and re-atain it after we've returned from the
667 		 * client.  This is to avoid any deadlock situations.
668 		 */
669 		LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
670 		    EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
671 		RDAGUNLOCK(rap);
672 		if ((*cb)(&lobj, client_data) == 0) {
673 			LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
674 			RDAGLOCK(rap);
675 			*abort_iter = 1;
676 			break;
677 		}
678 		RDAGLOCK(rap);
679 		lmaddr = (psaddr_t)NEXT(&rmap);
680 	}
681 	return (RD_OK);
682 }
683 
684 
685 rd_err_e
686 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
687 {
688 	Rtld_db_priv	db_priv;
689 	TList		list;
690 	TListnode	lnode;
691 	Addr		lnp;
692 	unsigned long	ident;
693 	rd_err_e	rc;
694 	uint_t		abort_iter = 0;
695 
696 	LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
697 	    client_data));
698 
699 	if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
700 	    sizeof (Rtld_db_priv)) != PS_OK) {
701 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
702 		    EC_ADDR(rap->rd_rtlddbpriv)));
703 		return (RD_DBERR);
704 	}
705 
706 	if (db_priv.rtd_dynlmlst == 0) {
707 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
708 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
709 		return (RD_NOMAPS);
710 	}
711 
712 	if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list,
713 	    sizeof (TList)) != PS_OK) {
714 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
715 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
716 		return (RD_DBERR);
717 	}
718 
719 	if (list.head == 0) {
720 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
721 		    EC_ADDR((uintptr_t)list.head)));
722 		return (RD_NOMAPS);
723 	}
724 
725 
726 	if (cb == 0) {
727 		LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
728 		return (RD_ERR);
729 	}
730 
731 	for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
732 		Lm_list	lml;
733 
734 		/*
735 		 * Iterate through the List of Lm_list's.
736 		 */
737 		if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
738 		    sizeof (TListnode)) != PS_OK) {
739 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
740 			    EC_ADDR(lnp)));
741 			return (RD_DBERR);
742 		}
743 
744 		if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml,
745 		    sizeof (Lm_list)) != PS_OK) {
746 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
747 			    EC_ADDR((uintptr_t)lnode.data)));
748 			return (RD_DBERR);
749 		}
750 
751 		/*
752 		 * Determine IDENT of current LM_LIST
753 		 */
754 		if (lml.lm_flags & LML_FLG_BASELM)
755 			ident = LM_ID_BASE;
756 		else if (lml.lm_flags & LML_FLG_RTLDLM)
757 			ident = LM_ID_LDSO;
758 		else
759 			ident = (unsigned long)lnode.data;
760 
761 		if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
762 		    cb, client_data, &abort_iter)) != RD_OK) {
763 			return (rc);
764 		}
765 		if (abort_iter)
766 			break;
767 	}
768 
769 	if (rc != RD_OK)
770 		return (rc);
771 
772 	if (rap->rd_helper.rh_ops != NULL)
773 		return (rap->rd_helper.rh_ops->rho_loadobj_iter(
774 		    rap->rd_helper.rh_data, cb, client_data));
775 
776 	return (RD_OK);
777 }
778