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