xref: /illumos-gate/usr/src/cmd/sgs/librtld_db/common/rd_elf.c (revision aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include	<stdlib.h>
27 #include	<stdio.h>
28 #include	<proc_service.h>
29 #include	<link.h>
30 #include	<rtld_db.h>
31 #include	<rtld.h>
32 #include	<alist.h>
33 #include	<list.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	TAPlist			APlist
57 #define	TLm_list		Lm_list
58 #define	TList			List
59 #define	TListnode		Listnode
60 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_64
61 #else	/* ELF32 */
62 #define	Rt_map			Rt_map32
63 #define	Rtld_db_priv		Rtld_db_priv32
64 #define	TAPlist			APlist32
65 #define	TLm_list		Lm_list32
66 #define	TList			List32
67 #define	TListnode		Listnode32
68 #define	Lm_list			Lm_list32
69 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
70 #endif	/* _ELF64 */
71 #else	/* _LP64 */
72 #define	TAPlist			APlist
73 #define	TLm_list		Lm_list
74 #define	TList			List
75 #define	TListnode		Listnode
76 #define	MSG_SYM_BRANDOPS	MSG_SYM_BRANDOPS_32
77 #endif	/* _LP64 */
78 
79 /*
80  * BrandZ added ps_pbrandname().  Many debuggers that link directly
81  * against librtld_db.so may not implement this interface.  Hence
82  * we won't call the function directly, instead we'll try to look it
83  * up using the linker first and only invoke it if we find it.
84  */
85 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
86     char *, size_t);
87 
88 rd_err_e
89 validate_rdebug32(struct rd_agent *rap)
90 {
91 	struct ps_prochandle	*php = rap->rd_psp;
92 	psaddr_t		db_privp;
93 	Rtld_db_priv		db_priv;
94 
95 	if (rap->rd_rdebug == 0)
96 		return (RD_ERR);
97 
98 	/*
99 	 * The rtld_db_priv structure contains both the traditional (exposed)
100 	 * r_debug structure as well as private data only available to
101 	 * this library.
102 	 */
103 	db_privp = rap->rd_rdebug;
104 
105 	/*
106 	 * Verify that librtld_db & rtld are at the proper revision
107 	 * levels.
108 	 */
109 	if (ps_pread(php, db_privp, (char *)&db_priv,
110 	    sizeof (Rtld_db_priv)) != PS_OK) {
111 		LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
112 		    EC_ADDR(db_privp)));
113 		return (RD_DBERR);
114 	}
115 
116 	if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
117 	    (db_priv.rtd_version > R_RTLDDB_VERSION)) {
118 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
119 		    db_priv.rtd_version, R_RTLDDB_VERSION));
120 		return (RD_NOCAPAB);
121 	}
122 
123 	/*
124 	 * Is the image being examined from a core file or not.
125 	 * If it is a core file then the following write will fail.
126 	 */
127 	if (ps_pwrite(php, db_privp, (char *)&db_priv,
128 	    sizeof (Rtld_db_priv)) != PS_OK)
129 		rap->rd_flags |= RDF_FL_COREFILE;
130 
131 	/*
132 	 * If this *is not* a core file then rtld_db & ld.so.1 are
133 	 * considered tightly coupled.  If the versions of our private
134 	 * data structures don't match - fail!
135 	 */
136 	if (((rap->rd_flags & RDF_FL_COREFILE) == 0) &&
137 	    (db_priv.rtd_version != R_RTLDDB_VERSION)) {
138 		LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
139 		    db_priv.rtd_version, R_RTLDDB_VERSION));
140 		return (RD_NOCAPAB);
141 	}
142 
143 	rap->rd_rdebugvers = db_priv.rtd_version;
144 	rap->rd_rtlddbpriv = db_privp;
145 
146 	LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
147 	    R_RTLDDB_VERSION, rap->rd_rdebugvers,
148 	    rap->rd_flags & RDF_FL_COREFILE));
149 	return (RD_OK);
150 }
151 
152 
153 rd_err_e
154 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
155 	Xword dyntag, Dyn *dyn)
156 {
157 	struct ps_prochandle	*php = rap->rd_psp;
158 	Dyn			d;
159 
160 	d.d_tag = DT_NULL;
161 	do {
162 		if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
163 		    PS_OK) {
164 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
165 			    EC_ADDR(dynaddr)));
166 			return (RD_DBERR);
167 		}
168 		dynaddr += sizeof (d);
169 		if (d.d_tag == dyntag)
170 			break;
171 	} while (d.d_tag != DT_NULL);
172 	if (d.d_tag == dyntag) {
173 		*dyn = d;
174 		LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
175 		    EC_ADDR(d.d_un.d_val)));
176 		return (RD_OK);
177 	}
178 	LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
179 	return (RD_DBERR);
180 }
181 
182 extern char rtld_db_helper_path[MAXPATHLEN];
183 
184 rd_err_e
185 _rd_reset32(struct rd_agent *rap)
186 {
187 	psaddr_t		symaddr;
188 	struct ps_prochandle	*php = rap->rd_psp;
189 	const auxv_t		*auxvp = NULL;
190 	rd_err_e		rc = RD_OK;
191 	char			brandname[MAXPATHLEN];
192 	char			brandlib[MAXPATHLEN];
193 	ps_pbrandname_fp_t	ps_pbrandname;
194 
195 	/*
196 	 * librtld_db attempts three different methods to find
197 	 * the r_debug structure which is required to
198 	 * initialize itself.  The methods are:
199 	 *	method1:
200 	 *		entirely independent of any text segment
201 	 *		and relies on the AT_SUN_LDDATA auxvector
202 	 *		to find the ld.so.1::rdebug structure.
203 	 *	method2:
204 	 *		lookup symbols in ld.so.1's symbol table
205 	 *		to find the r_debug symbol.
206 	 *	method3:
207 	 *		(old dbx method) dependent upon the
208 	 *		text segment/symbol table of the
209 	 *		executable and not ld.so.1.  We lookup the
210 	 *		_DYNAMIC symbol in the executable and look for
211 	 *		the DT_DEBUG entry in the .dynamic table.  This
212 	 *		points to rdebug.
213 	 *
214 	 * If none of that works - we fail.
215 	 */
216 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
217 	/*
218 	 * Method1
219 	 *
220 	 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
221 	 */
222 
223 	if (ps_pauxv(php, &auxvp) != PS_OK) {
224 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
225 		rc = RD_ERR;
226 	}
227 
228 	rap->rd_rdebug = 0;
229 
230 	if (auxvp != NULL) {
231 		rc = RD_ERR;
232 		while (auxvp->a_type != AT_NULL) {
233 			if (auxvp->a_type == AT_SUN_LDDATA) {
234 				/* LINTED */
235 				rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
236 				LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
237 				    rap->rd_rdebug));
238 				rc = validate_rdebug32(rap);
239 				break;
240 			}
241 			auxvp++;
242 		}
243 	}
244 
245 	/*
246 	 * method2 - look for r_rdebug symbol in ld.so.1
247 	 */
248 	if (rc != RD_OK) {
249 		/*
250 		 * If the AT_SUN_LDDATA auxv vector is not present
251 		 * fall back on doing a symlookup of
252 		 * the r_debug symbol.  This is for backward
253 		 * compatiblity with older OS's
254 		 */
255 		LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
256 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
257 		    &symaddr) != PS_OK) {
258 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
259 			    MSG_ORIG(MSG_SYM_DEBUG)));
260 			rc = RD_DBERR;
261 		} else {
262 			rap->rd_rdebug = symaddr;
263 			LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
264 			    EC_ADDR(symaddr)));
265 			rc = validate_rdebug32(rap);
266 		}
267 	}
268 
269 
270 	/*
271 	 * method3 - find DT_DEBUG in the executables .dynamic section.
272 	 */
273 	if (rc != RD_OK) {
274 		Dyn	dyn;
275 		if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
276 		    MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
277 			LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
278 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
279 			return (rc);
280 		}
281 		rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
282 		if (rc != RD_OK) {
283 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
284 			return (rc);
285 		}
286 		rap->rd_rdebug = dyn.d_un.d_ptr;
287 		rc = validate_rdebug32(rap);
288 		if (rc != RD_OK) {
289 			LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
290 			return (rc);
291 		}
292 	}
293 
294 	/*
295 	 * If we are debugging a branded executable, load the appropriate
296 	 * helper library, and call its initialization routine.  Being unable
297 	 * to load the helper library is not a critical error.  (Hopefully
298 	 * we'll still be able to access some objects in the target.)
299 	 */
300 	ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
301 	while ((ps_pbrandname != NULL) &&
302 	    (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
303 		const char *isa = "";
304 
305 #ifdef _LP64
306 		isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
307 #endif /* _LP64 */
308 
309 		if (rtld_db_helper_path[0] != '\0')
310 			(void) snprintf(brandlib, MAXPATHLEN,
311 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
312 			    rtld_db_helper_path,
313 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
314 			    brandname);
315 		else
316 			(void) snprintf(brandlib, MAXPATHLEN,
317 			    MSG_ORIG(MSG_DB_BRAND_HELPERPATH),
318 			    MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
319 			    brandname);
320 
321 		rap->rd_helper.rh_dlhandle = dlopen(brandlib,
322 		    RTLD_LAZY | RTLD_LOCAL);
323 		if (rap->rd_helper.rh_dlhandle == NULL) {
324 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
325 			    brandlib));
326 			break;
327 		}
328 
329 		rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
330 		    MSG_ORIG(MSG_SYM_BRANDOPS));
331 		if (rap->rd_helper.rh_ops == NULL) {
332 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
333 			    brandlib));
334 			(void) dlclose(rap->rd_helper.rh_dlhandle);
335 			rap->rd_helper.rh_dlhandle = NULL;
336 			break;
337 		}
338 
339 		rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
340 		    php);
341 		if (rap->rd_helper.rh_data == NULL) {
342 			LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
343 			(void) dlclose(rap->rd_helper.rh_dlhandle);
344 			rap->rd_helper.rh_dlhandle = NULL;
345 			rap->rd_helper.rh_ops = NULL;
346 			break;
347 		}
348 
349 		LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
350 		break;
351 
352 		/* NOTREACHED */
353 	}
354 
355 	if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
356 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
357 		    MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
358 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
359 			    MSG_ORIG(MSG_SYM_PREINIT)));
360 			return (RD_DBERR);
361 		}
362 		rap->rd_preinit = symaddr;
363 
364 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
365 		    MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
366 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
367 			    MSG_ORIG(MSG_SYM_POSTINIT)));
368 			return (RD_DBERR);
369 		}
370 		rap->rd_postinit = symaddr;
371 
372 		if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
373 		    MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
374 			LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
375 			    MSG_ORIG(MSG_SYM_DLACT)));
376 			return (RD_DBERR);
377 		}
378 		rap->rd_dlact = symaddr;
379 		rap->rd_tbinder = 0;
380 	}
381 
382 	return (RD_OK);
383 }
384 
385 rd_err_e
386 _rd_get_ehdr32(struct rd_agent *rap,
387     psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
388 {
389 	struct ps_prochandle	*php = rap->rd_psp;
390 	Shdr			shdr;
391 
392 	if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
393 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
394 		return (RD_ERR);
395 	}
396 	if (phnum == NULL)
397 		return (RD_OK);
398 
399 	if (ehdr->e_phnum != PN_XNUM) {
400 		*phnum = ehdr->e_phnum;
401 		return (RD_OK);
402 	}
403 
404 	/* deal with elf extended program headers */
405 	if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
406 		return (RD_ERR);
407 
408 	addr += ehdr->e_shoff;
409 	if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
410 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
411 		return (RD_ERR);
412 	}
413 
414 	if (shdr.sh_info == 0)
415 		return (RD_ERR);
416 
417 	*phnum = shdr.sh_info;
418 	return (RD_OK);
419 }
420 
421 rd_err_e
422 _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
423 {
424 	struct ps_prochandle	*php = rap->rd_psp;
425 	rd_err_e		err;
426 	uint_t			phnum;
427 	Ehdr			ehdr;
428 	Phdr			phdr;
429 	Dyn			*dynp;
430 	int			i;
431 
432 	/* We only need to muck with dyn elements for ET_DYN objects */
433 	if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
434 		return (err);
435 
436 	for (i = 0; i < phnum; i++) {
437 		psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
438 		if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
439 			LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
440 			return (RD_ERR);
441 		}
442 		if (phdr.p_type == PT_DYNAMIC)
443 			break;
444 	}
445 	if (i == phnum)
446 		return (RD_ERR);
447 
448 	if ((dynp = malloc(phdr.p_filesz)) == NULL)
449 		return (RD_ERR);
450 	if (ehdr.e_type == ET_DYN)
451 		phdr.p_vaddr += addr;
452 	if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
453 		free(dynp);
454 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
455 		    EC_ADDR(phdr.p_vaddr)));
456 		return (RD_ERR);
457 	}
458 
459 	*dynpp = dynp;
460 	if (dynpp_sz != NULL)
461 		*dynpp_sz = phdr.p_filesz;
462 	return (RD_OK);
463 }
464 
465 rd_err_e
466 _rd_event_enable32(rd_agent_t *rap, int onoff)
467 {
468 	struct ps_prochandle	*php = rap->rd_psp;
469 	Rtld_db_priv		rdb;
470 
471 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
472 	/*
473 	 * Tell the debugged process that debugging is occuring
474 	 * This will enable the storing of event messages so that
475 	 * the can be gathered by the debugger.
476 	 */
477 	if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
478 	    sizeof (Rtld_db_priv)) != PS_OK) {
479 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
480 		    EC_ADDR((uintptr_t)&rdb)));
481 		return (RD_DBERR);
482 	}
483 
484 	if (onoff)
485 		rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
486 	else
487 		rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
488 
489 	if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
490 	    sizeof (Rtld_db_priv)) != PS_OK) {
491 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
492 		    EC_ADDR((uintptr_t)&rdb)));
493 		return (RD_DBERR);
494 	}
495 
496 	return (RD_OK);
497 }
498 
499 
500 rd_err_e
501 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
502 {
503 	Rtld_db_priv	rdb;
504 
505 	if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
506 	    sizeof (Rtld_db_priv)) != PS_OK) {
507 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
508 		    EC_ADDR(rap->rd_rdebug)));
509 		return (RD_DBERR);
510 	}
511 	emsg->type = rdb.rtd_rdebug.r_rdevent;
512 	if (emsg->type == RD_DLACTIVITY) {
513 		switch (rdb.rtd_rdebug.r_state) {
514 			case RT_CONSISTENT:
515 				emsg->u.state = RD_CONSISTENT;
516 				break;
517 			case RT_ADD:
518 				emsg->u.state = RD_ADD;
519 				break;
520 			case RT_DELETE:
521 				emsg->u.state = RD_DELETE;
522 				break;
523 		}
524 	} else
525 		emsg->u.state = RD_NOSTATE;
526 
527 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
528 	    emsg->type, emsg->u.state));
529 
530 	return (RD_OK);
531 }
532 
533 
534 rd_err_e
535 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
536 {
537 	Rtld_db_priv		db_priv;
538 	struct ps_prochandle	*php = rap->rd_psp;
539 
540 	LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
541 
542 	if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
543 	    sizeof (Rtld_db_priv)) != PS_OK) {
544 		LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
545 		    EC_ADDR(rap->rd_rtlddbpriv)));
546 		return (RD_DBERR);
547 	}
548 #if	defined(_LP64) && !defined(_ELF64)
549 	/*LINTED*/
550 	db_priv.rtd_objpad = (uint32_t)padsize;
551 #else
552 	db_priv.rtd_objpad = padsize;
553 #endif
554 	if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
555 	    sizeof (Rtld_db_priv)) != PS_OK) {
556 		LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
557 		    EC_ADDR(rap->rd_rtlddbpriv)));
558 		return (RD_DBERR);
559 	}
560 	return (RD_OK);
561 }
562 
563 static rd_err_e
564 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
565 	rl_iter_f *cb, void *client_data, uint_t *abort_iterp)
566 {
567 	while (lmaddr) {
568 		Rt_map		rmap;
569 		rd_loadobj_t	lobj;
570 		int		i;
571 		ulong_t		off;
572 		Ehdr		ehdr;
573 		Phdr		phdr;
574 
575 		if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
576 		    sizeof (Rt_map)) != PS_OK) {
577 			LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
578 			return (RD_DBERR);
579 		}
580 
581 		/*
582 		 * As of 'VERSION5' we only report objects
583 		 * which have been fully relocated.  While the maps
584 		 * might be in a consistent state - if a object hasn't
585 		 * been relocated - it's not really ready for the debuggers
586 		 * to examine.  This is mostly due to the fact that we
587 		 * might still be mucking with the text-segment, if
588 		 * we are - we could conflict with any break-points
589 		 * the debuggers might have set.
590 		 */
591 		if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
592 			if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
593 				lmaddr = (psaddr_t)NEXT(&rmap);
594 				continue;
595 			}
596 		}
597 
598 		lobj.rl_base = (psaddr_t)ADDR(&rmap);
599 		lobj.rl_flags = 0;
600 		lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
601 		if ((rap->rd_helper.rh_ops != NULL) &&
602 		    (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
603 			lobj.rl_lmident =
604 			    rap->rd_helper.rh_ops->rho_lmid;
605 		else
606 			lobj.rl_lmident = ident;
607 
608 		/*
609 		 * refnameaddr is only valid from a core file
610 		 * which is VERSION3 or greater.
611 		 */
612 		if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
613 			lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
614 			lobj.rl_bend = 0;
615 			lobj.rl_padstart = 0;
616 			lobj.rl_padend = 0;
617 		} else {
618 			lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
619 			lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
620 			lobj.rl_padstart = PADSTART(&rmap);
621 			lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
622 
623 		}
624 
625 		if (rtld_db_version >= RD_VERSION2)
626 			if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
627 				lobj.rl_flags |= RD_FLG_MEM_OBJECT;
628 		if (rtld_db_version >= RD_VERSION2) {
629 			lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
630 		}
631 
632 		if (rtld_db_version >= RD_VERSION4)
633 			lobj.rl_tlsmodid = TLSMODID(&rmap);
634 
635 		/*
636 		 * Look for beginning of data segment.
637 		 *
638 		 * NOTE: the data segment can only be found for full
639 		 *	processes and not from core images.
640 		 */
641 		lobj.rl_data_base = 0;
642 		if (rap->rd_flags & RDF_FL_COREFILE)
643 			lobj.rl_data_base = 0;
644 		else {
645 			off = ADDR(&rmap);
646 			if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
647 			    sizeof (Ehdr)) != PS_OK) {
648 				LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
649 				return (RD_DBERR);
650 			}
651 			off += sizeof (Ehdr);
652 			for (i = 0; i < ehdr.e_phnum; i++) {
653 				if (ps_pread(rap->rd_psp, off, (char *)&phdr,
654 				    sizeof (Phdr)) != PS_OK) {
655 					LOG(ps_plog(MSG_ORIG(
656 					    MSG_DB_LKMAPFAIL)));
657 					return (RD_DBERR);
658 				}
659 				if ((phdr.p_type == PT_LOAD) &&
660 				    (phdr.p_flags & PF_W)) {
661 					lobj.rl_data_base = phdr.p_vaddr;
662 					if (ehdr.e_type == ET_DYN)
663 						lobj.rl_data_base +=
664 						    ADDR(&rmap);
665 					break;
666 				}
667 				off += ehdr.e_phentsize;
668 			}
669 		}
670 
671 		/*
672 		 * When we transfer control to the client we free the
673 		 * lock and re-atain it after we've returned from the
674 		 * client.  This is to avoid any deadlock situations.
675 		 */
676 		LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
677 		    EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
678 		RDAGUNLOCK(rap);
679 		if ((*cb)(&lobj, client_data) == 0) {
680 			LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
681 			RDAGLOCK(rap);
682 			*abort_iterp = 1;
683 			break;
684 		}
685 		RDAGLOCK(rap);
686 		lmaddr = (psaddr_t)NEXT(&rmap);
687 	}
688 	return (RD_OK);
689 }
690 
691 
692 static rd_err_e
693 _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data,
694     uint_t *abort_iterp)
695 {
696 	Rtld_db_priv	db_priv;
697 	TAPlist		apl;
698 	uintptr_t	datap, nitems;
699 	Addr		addr;
700 	rd_err_e	rc;
701 
702 	LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
703 	    client_data));
704 
705 	/*
706 	 * First, determine whether the link-map information has been
707 	 * established.  Some debuggers have made an initial call to this
708 	 * function with a null call back function (cb), but expect a
709 	 * RD_NOMAPS error return rather than a RD_ERR return when the
710 	 * link-maps aren't available.
711 	 */
712 	if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
713 	    sizeof (Rtld_db_priv)) != PS_OK) {
714 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
715 		    EC_ADDR(rap->rd_rtlddbpriv)));
716 		return (RD_DBERR);
717 	}
718 
719 	if (db_priv.rtd_dynlmlst == NULL) {
720 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
721 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
722 		return (RD_NOMAPS);
723 	}
724 
725 	if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr,
726 	    sizeof (Addr)) != PS_OK) {
727 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
728 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
729 		return (RD_DBERR);
730 	}
731 
732 	if (addr == NULL) {
733 		LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
734 		    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
735 		return (RD_NOMAPS);
736 	}
737 
738 	/*
739 	 * Having determined we have link-maps, ensure we have an iterator
740 	 * call back function.
741 	 */
742 	if (cb == NULL) {
743 		LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
744 		return (RD_ERR);
745 	}
746 
747 	/*
748 	 * As of VERSION6, rtd_dynlmlst points to an APlist.  Prior to VERSION6
749 	 * rtd_dynlmlst pointed to a List.  But, there was a window where the
750 	 * version was not incremented, and this must be worked around by
751 	 * interpreting the APlist data.  Read the initial APlist information.
752 	 */
753 	if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl,
754 	    sizeof (TAPlist)) != PS_OK) {
755 		LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
756 		    EC_ADDR((uintptr_t)addr)));
757 		return (RD_DBERR);
758 	}
759 
760 	/*
761 	 * The rtd_dynlmlst change from a List to an APlist occurred under
762 	 * 6801536 in snv_112.  However, this change neglected to preserve
763 	 * backward compatibility by maintaining List processing and using a
764 	 * version increment to detect the change.  6862967, intergrated in
765 	 * snv_121 corrects the version detection.  However, to catch objects
766 	 * built between these releases, we look at the first element of the
767 	 * APlist.  apl_arritems indicates the number of APlist items that are
768 	 * available.  This was originally initialized with a AL_CNT_DYNLIST
769 	 * value of 2 (one entry for LM_ID_BASE and one entry for LM_ID_LDSO).
770 	 * It is possible that the use of an auditor results in an additional
771 	 * link-map list, in which case the original apl_arritems would have
772 	 * been doubled.
773 	 *
774 	 * Therefore, if the debugging verion is VERSION6, or the apl_arritems
775 	 * entry has a value less than or equal to 4 and the debugging version
776 	 * is VERSION5, then we process APlists.  Otherwise, fall back to List
777 	 * processing.
778 	 */
779 	if ((rap->rd_rdebugvers >= R_RTLDDB_VERSION6) ||
780 	    ((rap->rd_rdebugvers == R_RTLDDB_VERSION5) &&
781 	    (apl.apl_arritems <= 4))) {
782 		/*
783 		 * Iterate through each apl.ap_data[] entry.
784 		 */
785 		for (datap = (uintptr_t)((char *)(uintptr_t)addr +
786 		    ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0;
787 		    nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) {
788 			TLm_list	lm;
789 			ulong_t		ident;
790 
791 			/*
792 			 * Obtain the Lm_list address for this apl.ap_data[]
793 			 * entry.
794 			 */
795 			if (ps_pread(rap->rd_psp, (psaddr_t)datap,
796 			    (char *)&addr, sizeof (Addr)) != PS_OK) {
797 				LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
798 				    EC_ADDR(datap)));
799 				return (RD_DBERR);
800 			}
801 
802 			/*
803 			 * Obtain the Lm_list data for this Lm_list address.
804 			 */
805 			if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm,
806 			    sizeof (TLm_list)) != PS_OK) {
807 				LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6),
808 				    EC_ADDR((uintptr_t)addr)));
809 				return (RD_DBERR);
810 			}
811 
812 			/*
813 			 * Determine IDENT of current LM_LIST
814 			 */
815 			if (lm.lm_flags & LML_FLG_BASELM)
816 				ident = LM_ID_BASE;
817 			else if (lm.lm_flags & LML_FLG_RTLDLM)
818 				ident = LM_ID_LDSO;
819 			else
820 				ident = (ulong_t)addr;
821 
822 			if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head,
823 			    cb, client_data, abort_iterp)) != RD_OK)
824 				return (rc);
825 
826 			if (*abort_iterp != 0)
827 				break;
828 		}
829 	} else {
830 		TList		list;
831 		TListnode	lnode;
832 		Addr		lnp;
833 
834 		/*
835 		 * Re-read the dynlmlst address to obtain a List structure.
836 		 */
837 		if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst,
838 		    (char *)&list, sizeof (TList)) != PS_OK) {
839 			LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
840 			    EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
841 			return (RD_DBERR);
842 		}
843 
844 		/*
845 		 * Iterate through the link-map list.
846 		 */
847 		for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
848 			Lm_list	lml;
849 			ulong_t	ident;
850 
851 			/*
852 			 * Iterate through the List of Lm_list's.
853 			 */
854 			if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
855 			    sizeof (TListnode)) != PS_OK) {
856 				LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
857 				    EC_ADDR(lnp)));
858 					return (RD_DBERR);
859 			}
860 
861 			if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data,
862 			    (char *)&lml, sizeof (Lm_list)) != PS_OK) {
863 				LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
864 				    EC_ADDR((uintptr_t)lnode.data)));
865 					return (RD_DBERR);
866 			}
867 
868 			/*
869 			 * Determine IDENT of current LM_LIST
870 			 */
871 			if (lml.lm_flags & LML_FLG_BASELM)
872 				ident = LM_ID_BASE;
873 			else if (lml.lm_flags & LML_FLG_RTLDLM)
874 				ident = LM_ID_LDSO;
875 			else
876 				ident = (unsigned long)lnode.data;
877 
878 			if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
879 			    cb, client_data, abort_iterp)) != RD_OK)
880 				return (rc);
881 
882 			if (*abort_iterp != 0)
883 				break;
884 		}
885 	}
886 
887 	return (rc);
888 }
889 
890 rd_err_e
891 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
892 {
893 	rd_err_e	rc, rc_brand = RD_OK;
894 	uint_t		abort_iter = 0;
895 
896 	/* First iterate over the native target objects */
897 	rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter);
898 	if (abort_iter != 0)
899 		return (rc);
900 
901 	/* Then iterate over any branded objects. */
902 	if ((rap->rd_helper.rh_ops != NULL) &&
903 	    (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL))
904 		rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter(
905 		    rap->rd_helper.rh_data, cb, client_data);
906 
907 	rc = (rc != RD_OK) ? rc : rc_brand;
908 	return (rc);
909 }
910