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