1628e3cbeSEdward Pilatowicz /*
2628e3cbeSEdward Pilatowicz  * CDDL HEADER START
3628e3cbeSEdward Pilatowicz  *
4628e3cbeSEdward Pilatowicz  * The contents of this file are subject to the terms of the
5628e3cbeSEdward Pilatowicz  * Common Development and Distribution License (the "License").
6628e3cbeSEdward Pilatowicz  * You may not use this file except in compliance with the License.
7628e3cbeSEdward Pilatowicz  *
8628e3cbeSEdward Pilatowicz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9628e3cbeSEdward Pilatowicz  * or http://www.opensolaris.org/os/licensing.
10628e3cbeSEdward Pilatowicz  * See the License for the specific language governing permissions
11628e3cbeSEdward Pilatowicz  * and limitations under the License.
12628e3cbeSEdward Pilatowicz  *
13628e3cbeSEdward Pilatowicz  * When distributing Covered Code, include this CDDL HEADER in each
14628e3cbeSEdward Pilatowicz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15628e3cbeSEdward Pilatowicz  * If applicable, add the following below this CDDL HEADER, with the
16628e3cbeSEdward Pilatowicz  * fields enclosed by brackets "[]" replaced with your own identifying
17628e3cbeSEdward Pilatowicz  * information: Portions Copyright [yyyy] [name of copyright owner]
18628e3cbeSEdward Pilatowicz  *
19628e3cbeSEdward Pilatowicz  * CDDL HEADER END
20628e3cbeSEdward Pilatowicz  */
21628e3cbeSEdward Pilatowicz 
22628e3cbeSEdward Pilatowicz /*
23*80e2ca85S  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24628e3cbeSEdward Pilatowicz  */
25628e3cbeSEdward Pilatowicz 
26628e3cbeSEdward Pilatowicz #include <assert.h>
27628e3cbeSEdward Pilatowicz #include <stdio.h>
28628e3cbeSEdward Pilatowicz #include <stdlib.h>
29628e3cbeSEdward Pilatowicz #include <string.h>
30628e3cbeSEdward Pilatowicz #include <strings.h>
31628e3cbeSEdward Pilatowicz #include <libproc.h>
32628e3cbeSEdward Pilatowicz #include <proc_service.h>
33628e3cbeSEdward Pilatowicz #include <synch.h>
34628e3cbeSEdward Pilatowicz #include <sys/types.h>
35628e3cbeSEdward Pilatowicz #include <sys/link.h>
36628e3cbeSEdward Pilatowicz #include <rtld_db.h>
37*80e2ca85S #include <sys/brand.h>
38628e3cbeSEdward Pilatowicz 
39628e3cbeSEdward Pilatowicz /*
40628e3cbeSEdward Pilatowicz  * ATTENTION:
41628e3cbeSEdward Pilatowicz  *	Librtl_db brand plugin libraries should NOT directly invoke any
42628e3cbeSEdward Pilatowicz  *	libproc.so interfaces or be linked against libproc.  If a librtl_db
43628e3cbeSEdward Pilatowicz  *	brand plugin library uses libproc.so interfaces then it may break
44628e3cbeSEdward Pilatowicz  *	any other librtld_db consumers (like mdb) that tries to attach
45628e3cbeSEdward Pilatowicz  *	to a branded process.  The only safe interfaces that the a librtld_db
46628e3cbeSEdward Pilatowicz  *	brand plugin library can use to access a target process are the
47628e3cbeSEdward Pilatowicz  *	proc_service(3PROC) apis.
48628e3cbeSEdward Pilatowicz  */
49628e3cbeSEdward Pilatowicz 
50628e3cbeSEdward Pilatowicz /*
51628e3cbeSEdward Pilatowicz  * M_DATA comes from some streams header file but is also redifined in
52628e3cbeSEdward Pilatowicz  * _rtld_db.h, so nuke the old streams definition here.
53628e3cbeSEdward Pilatowicz  */
54628e3cbeSEdward Pilatowicz #ifdef M_DATA
55628e3cbeSEdward Pilatowicz #undef M_DATA
56628e3cbeSEdward Pilatowicz #endif /* M_DATA */
57628e3cbeSEdward Pilatowicz 
58628e3cbeSEdward Pilatowicz /*
59628e3cbeSEdward Pilatowicz  * For 32-bit versions of this library, this file get's compiled once.
60628e3cbeSEdward Pilatowicz  * For 64-bit versions of this library, this file get's compiled twice,
61628e3cbeSEdward Pilatowicz  * once with _ELF64 defined and once without.  The expectation is that
62628e3cbeSEdward Pilatowicz  * the 64-bit version of the library can properly deal with both 32-bit
63628e3cbeSEdward Pilatowicz  * and 64-bit elf files, hence in the 64-bit library there are two copies
64628e3cbeSEdward Pilatowicz  * of all the interfaces in this file, one set named *32 and one named *64.
65628e3cbeSEdward Pilatowicz  *
66628e3cbeSEdward Pilatowicz  * This also means that we need to be careful when declaring local pointers
67628e3cbeSEdward Pilatowicz  * that point to objects in another processes address space, since these
68628e3cbeSEdward Pilatowicz  * pointers may not match the current processes pointer width.  Basically,
69628e3cbeSEdward Pilatowicz  * we should not use any objects that change size between 32 and 64 bit
70628e3cbeSEdward Pilatowicz  * modes like: long, void *, uintprt_t, caddr_t, psaddr_t, size_t, etc.
71628e3cbeSEdward Pilatowicz  * Instead we should declare all pointers as uint32_t.  Then when we
72628e3cbeSEdward Pilatowicz  * are compiled to deal with 64-bit targets we'll re-define uing32_t
73628e3cbeSEdward Pilatowicz  * to be a uint64_t.
74628e3cbeSEdward Pilatowicz  */
75628e3cbeSEdward Pilatowicz #ifdef _LP64
76628e3cbeSEdward Pilatowicz #ifdef _ELF64
77628e3cbeSEdward Pilatowicz #define	uint32_t			uint64_t
78628e3cbeSEdward Pilatowicz #define	Elf32_Dyn			Elf64_Dyn
79628e3cbeSEdward Pilatowicz #define	validate_rdebug32		validate_rdebug64
80628e3cbeSEdward Pilatowicz #define	_rd_loadobj_iter32		_rd_loadobj_iter64
81628e3cbeSEdward Pilatowicz #define	_rd_get_dyns32			_rd_get_dyns64
82628e3cbeSEdward Pilatowicz #define	dummy_ldb32			dummy_ldb64
83628e3cbeSEdward Pilatowicz #define	dummy_ldb_init32		dummy_ldb_init64
84628e3cbeSEdward Pilatowicz #define	dummy_ldb_fini32		dummy_ldb_fini64
85628e3cbeSEdward Pilatowicz #define	dummy_ldb_loadobj_iter32	dummy_ldb_loadobj_iter64
86628e3cbeSEdward Pilatowicz #define	dummy_ldb_get_dyns32		dummy_ldb_get_dyns64
87*80e2ca85S #define	brand_ldb_init32		brand_ldb_init64
88*80e2ca85S #define	brand_ldb_fini32		brand_ldb_fini64
89*80e2ca85S #define	brand_ldb_loadobj_iter32	brand_ldb_loadobj_iter64
90*80e2ca85S #define	brand_ldb_get_dyns32		brand_ldb_get_dyns64
91628e3cbeSEdward Pilatowicz #endif /* _ELF64 */
92628e3cbeSEdward Pilatowicz #endif /* _LP64 */
93628e3cbeSEdward Pilatowicz 
94628e3cbeSEdward Pilatowicz /* Included from usr/src/cmd/sgs/librtld_db/common */
95628e3cbeSEdward Pilatowicz #include <_rtld_db.h>
96628e3cbeSEdward Pilatowicz 
97628e3cbeSEdward Pilatowicz /*ARGSUSED*/
98628e3cbeSEdward Pilatowicz static rd_helper_data_t
dummy_ldb_init32(rd_agent_t * rap,struct ps_prochandle * php)99628e3cbeSEdward Pilatowicz dummy_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php)
100628e3cbeSEdward Pilatowicz {
101628e3cbeSEdward Pilatowicz 	return (NULL);
102628e3cbeSEdward Pilatowicz }
103628e3cbeSEdward Pilatowicz 
104628e3cbeSEdward Pilatowicz /*ARGSUSED*/
105628e3cbeSEdward Pilatowicz static void
dummy_ldb_fini32(rd_helper_data_t rhd)106628e3cbeSEdward Pilatowicz dummy_ldb_fini32(rd_helper_data_t rhd)
107628e3cbeSEdward Pilatowicz {
108628e3cbeSEdward Pilatowicz }
109628e3cbeSEdward Pilatowicz 
110628e3cbeSEdward Pilatowicz /*ARGSUSED*/
111628e3cbeSEdward Pilatowicz static int
dummy_ldb_loadobj_iter32(rd_helper_data_t rhd,rl_iter_f * cb,void * client_data)112628e3cbeSEdward Pilatowicz dummy_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data)
113628e3cbeSEdward Pilatowicz {
114628e3cbeSEdward Pilatowicz 	return (RD_OK);
115628e3cbeSEdward Pilatowicz }
116628e3cbeSEdward Pilatowicz 
117628e3cbeSEdward Pilatowicz /*ARGSUSED*/
118628e3cbeSEdward Pilatowicz static rd_err_e
dummy_ldb_get_dyns32(rd_helper_data_t rhd,psaddr_t addr,void ** dynpp,size_t * dynpp_sz)119628e3cbeSEdward Pilatowicz dummy_ldb_get_dyns32(rd_helper_data_t rhd,
120628e3cbeSEdward Pilatowicz     psaddr_t addr, void **dynpp, size_t *dynpp_sz)
121628e3cbeSEdward Pilatowicz {
122628e3cbeSEdward Pilatowicz 	*dynpp = NULL;
123628e3cbeSEdward Pilatowicz 	*dynpp_sz = 0;
124628e3cbeSEdward Pilatowicz 	return (RD_OK);
125628e3cbeSEdward Pilatowicz }
126628e3cbeSEdward Pilatowicz 
127628e3cbeSEdward Pilatowicz static rd_helper_ops_t dummy_ldb32 = {
128628e3cbeSEdward Pilatowicz 	LM_ID_BRAND,
129628e3cbeSEdward Pilatowicz 	dummy_ldb_init32,
130628e3cbeSEdward Pilatowicz 	dummy_ldb_fini32,
131628e3cbeSEdward Pilatowicz 	dummy_ldb_loadobj_iter32,
132628e3cbeSEdward Pilatowicz 	dummy_ldb_get_dyns32
133628e3cbeSEdward Pilatowicz };
134628e3cbeSEdward Pilatowicz 
135628e3cbeSEdward Pilatowicz static uint32_t
brand_ldb_getauxval32(struct ps_prochandle * php,int type)136*80e2ca85S brand_ldb_getauxval32(struct ps_prochandle *php, int type)
137628e3cbeSEdward Pilatowicz {
138628e3cbeSEdward Pilatowicz 	const auxv_t		*auxvp = NULL;
139628e3cbeSEdward Pilatowicz 
140628e3cbeSEdward Pilatowicz 	if (ps_pauxv(php, &auxvp) != PS_OK)
141628e3cbeSEdward Pilatowicz 		return ((uint32_t)-1);
142628e3cbeSEdward Pilatowicz 
143628e3cbeSEdward Pilatowicz 	while (auxvp->a_type != AT_NULL) {
144628e3cbeSEdward Pilatowicz 		if (auxvp->a_type == type)
145628e3cbeSEdward Pilatowicz 			return ((uint32_t)(uintptr_t)auxvp->a_un.a_ptr);
146628e3cbeSEdward Pilatowicz 		auxvp++;
147628e3cbeSEdward Pilatowicz 	}
148628e3cbeSEdward Pilatowicz 	return ((uint32_t)-1);
149628e3cbeSEdward Pilatowicz }
150628e3cbeSEdward Pilatowicz 
151628e3cbeSEdward Pilatowicz /*
152628e3cbeSEdward Pilatowicz  * Normally, the native Solaris librtldb_db plugin uses a bunch of different
153628e3cbeSEdward Pilatowicz  * methods to try and find the rdebug structure associated with the target
154628e3cbeSEdward Pilatowicz  * process we're debugging.  For details on the different methods see
155628e3cbeSEdward Pilatowicz  * _rd_reset32().  Thankfully our job is easier.  We know that the brand
156628e3cbeSEdward Pilatowicz  * library is always linked against the native linker, and when the
157628e3cbeSEdward Pilatowicz  * process was first executed we saved off a pointer to the brand linkers
158628e3cbeSEdward Pilatowicz  * rdebug structure in one of our brand specific aux vectors,
159*80e2ca85S  * AT_SUN_BRAND_COMMON_LDDATA.  So we'll just look that up here.
160628e3cbeSEdward Pilatowicz  */
161628e3cbeSEdward Pilatowicz /*ARGSUSED*/
162628e3cbeSEdward Pilatowicz static rd_helper_data_t
brand_ldb_init32(rd_agent_t * rap,struct ps_prochandle * php)163*80e2ca85S brand_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php)
164628e3cbeSEdward Pilatowicz {
165628e3cbeSEdward Pilatowicz 	struct rd_agent	*rap_new;
166628e3cbeSEdward Pilatowicz 	uint32_t	lddata_addr;
167628e3cbeSEdward Pilatowicz 	int		rd_dmodel;
168628e3cbeSEdward Pilatowicz 
169628e3cbeSEdward Pilatowicz 	if (ps_pdmodel(php, &rd_dmodel) != PS_OK) {
170*80e2ca85S 		ps_plog("brand_ldb_init: lookup of data model failed");
171628e3cbeSEdward Pilatowicz 		return (NULL);
172628e3cbeSEdward Pilatowicz 	}
173628e3cbeSEdward Pilatowicz #ifdef _ELF64
174628e3cbeSEdward Pilatowicz 	assert(rd_dmodel == PR_MODEL_LP64);
175628e3cbeSEdward Pilatowicz #else /* !_ELF64 */
176628e3cbeSEdward Pilatowicz 	assert(rd_dmodel == PR_MODEL_ILP32);
177628e3cbeSEdward Pilatowicz #endif /* !_ELF64 */
178628e3cbeSEdward Pilatowicz 
179*80e2ca85S 	lddata_addr = brand_ldb_getauxval32(php, AT_SUN_BRAND_COMMON_LDDATA);
180628e3cbeSEdward Pilatowicz 	if (lddata_addr == (uint32_t)-1) {
181*80e2ca85S 		ps_plog("brand_ldb_init: no LDDATA found in aux vector");
182628e3cbeSEdward Pilatowicz 		return (NULL);
183628e3cbeSEdward Pilatowicz 	}
184*80e2ca85S 	ps_plog("brand_ldb_init: found LDDATA auxv ld.so.1 data seg "
185628e3cbeSEdward Pilatowicz 	    "at: 0x%p", lddata_addr);
186628e3cbeSEdward Pilatowicz 
187628e3cbeSEdward Pilatowicz 	/*
188628e3cbeSEdward Pilatowicz 	 * Ok.  So this is kinda ugly.  Basically we know that we're going to
189628e3cbeSEdward Pilatowicz 	 * be parsing data from link maps that are generated by a Solaris
190628e3cbeSEdward Pilatowicz 	 * linker.  As it turns out, that's exactly what the default
191628e3cbeSEdward Pilatowicz 	 * Solaris librtld_db library is designed to do.  So rather than
192628e3cbeSEdward Pilatowicz 	 * duplicate all that link map parsing code here we'll simply
193628e3cbeSEdward Pilatowicz 	 * invoke the native librtld_db that normally does this, and when
194628e3cbeSEdward Pilatowicz 	 * we do we'll point them at our emulation libraries link map.
195628e3cbeSEdward Pilatowicz 	 *
196628e3cbeSEdward Pilatowicz 	 * Of course these interfacess aren't really public interfaces
197628e3cbeSEdward Pilatowicz 	 * and they take a "struct rd_agent" as a parameter.  So here
198628e3cbeSEdward Pilatowicz 	 * we'll allocate and initialize a new "struct rd_agent", point
199628e3cbeSEdward Pilatowicz 	 * it at our emulation libraries link map, and initialize just
200628e3cbeSEdward Pilatowicz 	 * enough of the structure to make the librtld_db interfaces
201628e3cbeSEdward Pilatowicz 	 * that we want to use happy.
202628e3cbeSEdward Pilatowicz 	 */
203628e3cbeSEdward Pilatowicz 	if ((rap_new = calloc(sizeof (*rap_new), 1)) == NULL) {
204*80e2ca85S 		ps_plog("brand_ldb_init: can't allocate memory");
205628e3cbeSEdward Pilatowicz 		return (NULL);
206628e3cbeSEdward Pilatowicz 	}
207628e3cbeSEdward Pilatowicz 	rap_new->rd_dmodel = rd_dmodel;
208628e3cbeSEdward Pilatowicz 	rap_new->rd_psp = php;
209628e3cbeSEdward Pilatowicz 	rap_new->rd_rdebug = lddata_addr;
210628e3cbeSEdward Pilatowicz 	(void) mutex_init(&rap_new->rd_mutex, USYNC_THREAD, 0);
211628e3cbeSEdward Pilatowicz 
212628e3cbeSEdward Pilatowicz 	/*
213628e3cbeSEdward Pilatowicz 	 * When we get invoked from librtld_db, and we call back into it,
214628e3cbeSEdward Pilatowicz 	 * librtld_db will once again check if there is a plugin and
215628e3cbeSEdward Pilatowicz 	 * invoke it.  Since we don't want to enter a recursive loop
216628e3cbeSEdward Pilatowicz 	 * we're going to specify a different plugin interface for
217628e3cbeSEdward Pilatowicz 	 * our linkmap, and these new plugin interfaces won't actually
218628e3cbeSEdward Pilatowicz 	 * do anything other than return.
219628e3cbeSEdward Pilatowicz 	 */
220628e3cbeSEdward Pilatowicz 	rap_new->rd_helper.rh_ops = &dummy_ldb32;
221628e3cbeSEdward Pilatowicz 
222628e3cbeSEdward Pilatowicz 	/*
223628e3cbeSEdward Pilatowicz 	 * validate_rdebug32() requires the following "struct rd_agent"
224628e3cbeSEdward Pilatowicz 	 * members to be initialized:
225628e3cbeSEdward Pilatowicz 	 *	rd_psp, rd_rdebug
226628e3cbeSEdward Pilatowicz 	 *
227628e3cbeSEdward Pilatowicz 	 * validate_rdebug32() initializes the following "struct rd_agent"
228628e3cbeSEdward Pilatowicz 	 * members:
229628e3cbeSEdward Pilatowicz 	 *	rd_flags, rd_rdebugvers, rd_rtlddbpriv
230628e3cbeSEdward Pilatowicz 	 */
231628e3cbeSEdward Pilatowicz 	if (validate_rdebug32(rap_new) != RD_OK) {
232*80e2ca85S 		ps_plog("brand_ldb_init: can't find valid r_debug data");
233628e3cbeSEdward Pilatowicz 		free(rap_new);
234628e3cbeSEdward Pilatowicz 		return (NULL);
235628e3cbeSEdward Pilatowicz 	}
236628e3cbeSEdward Pilatowicz 
237*80e2ca85S 	ps_plog("brand_ldb_init: finished, helper_data=0x%p", rap_new);
238628e3cbeSEdward Pilatowicz 	return ((rd_helper_data_t)rap_new);
239628e3cbeSEdward Pilatowicz }
240628e3cbeSEdward Pilatowicz 
241628e3cbeSEdward Pilatowicz static void
brand_ldb_fini32(rd_helper_data_t rhd)242*80e2ca85S brand_ldb_fini32(rd_helper_data_t rhd)
243628e3cbeSEdward Pilatowicz {
244628e3cbeSEdward Pilatowicz 	struct rd_agent	*rap = (struct rd_agent *)rhd;
245*80e2ca85S 	ps_plog("brand_ldb_fini: cleaning up brand helper");
246628e3cbeSEdward Pilatowicz 	free(rap);
247628e3cbeSEdward Pilatowicz }
248628e3cbeSEdward Pilatowicz 
249628e3cbeSEdward Pilatowicz /*ARGSUSED*/
250628e3cbeSEdward Pilatowicz static int
brand_ldb_loadobj_iter32(rd_helper_data_t rhd,rl_iter_f * cb,void * client_data)251*80e2ca85S brand_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data)
252628e3cbeSEdward Pilatowicz {
253628e3cbeSEdward Pilatowicz 	struct rd_agent	*rap = (struct rd_agent *)rhd;
254628e3cbeSEdward Pilatowicz 	int		err;
255628e3cbeSEdward Pilatowicz 
256*80e2ca85S 	ps_plog("brand_ldb_loadobj_iter(helper_data=0x%p)", rhd);
257628e3cbeSEdward Pilatowicz 	assert(rap->rd_psp == php);
258628e3cbeSEdward Pilatowicz 	RDAGLOCK(rap);
259628e3cbeSEdward Pilatowicz 	/*
260628e3cbeSEdward Pilatowicz 	 * _rd_loadobj_iter32() requires the following "struct rd_agent"
261628e3cbeSEdward Pilatowicz 	 * members to be initialized:
262628e3cbeSEdward Pilatowicz 	 * 	rd_rtlddbpriv, rd_rdebugvers, rd_flags,
263628e3cbeSEdward Pilatowicz 	 * 	rd_helper.rh_ops, rd_dmodel
264628e3cbeSEdward Pilatowicz 	 */
265628e3cbeSEdward Pilatowicz 	err = _rd_loadobj_iter32(rap, cb, client_data);
266628e3cbeSEdward Pilatowicz 	RDAGUNLOCK(rap);
267*80e2ca85S 	ps_plog("brand_ldb_loadobj_iter: finished, err = %d", err);
268628e3cbeSEdward Pilatowicz 	return (err);
269628e3cbeSEdward Pilatowicz }
270628e3cbeSEdward Pilatowicz 
271628e3cbeSEdward Pilatowicz /*ARGSUSED*/
272628e3cbeSEdward Pilatowicz static rd_err_e
brand_ldb_get_dyns32(rd_helper_data_t rhd,psaddr_t addr,void ** dynpp,size_t * dynpp_sz)273*80e2ca85S brand_ldb_get_dyns32(rd_helper_data_t rhd,
274628e3cbeSEdward Pilatowicz     psaddr_t addr, void **dynpp, size_t *dynpp_sz)
275628e3cbeSEdward Pilatowicz {
276628e3cbeSEdward Pilatowicz 	struct rd_agent	*rap = (struct rd_agent *)rhd;
277628e3cbeSEdward Pilatowicz 	int		err;
278628e3cbeSEdward Pilatowicz 
279*80e2ca85S 	ps_plog("brand_ldb_get_dyns(helper_data=0x%p)", rhd);
280628e3cbeSEdward Pilatowicz 	err = _rd_get_dyns32(rap, addr, (Elf32_Dyn **)dynpp, dynpp_sz);
281*80e2ca85S 	ps_plog("brand_ldb_get_dyns: finished, err = %d", err);
282628e3cbeSEdward Pilatowicz 	return (err);
283628e3cbeSEdward Pilatowicz }
284628e3cbeSEdward Pilatowicz 
285628e3cbeSEdward Pilatowicz /*
286628e3cbeSEdward Pilatowicz  * Librtld_db plugin linkage struct.
287628e3cbeSEdward Pilatowicz  *
288628e3cbeSEdward Pilatowicz  * When we get loaded by librtld_db, it will look for the symbol below
289628e3cbeSEdward Pilatowicz  * to find our plugin entry points.
290628e3cbeSEdward Pilatowicz  */
291628e3cbeSEdward Pilatowicz rd_helper_ops_t RTLD_DB_BRAND_OPS = {
292628e3cbeSEdward Pilatowicz 	LM_ID_NONE,
293*80e2ca85S 	brand_ldb_init32,
294*80e2ca85S 	brand_ldb_fini32,
295*80e2ca85S 	brand_ldb_loadobj_iter32,
296*80e2ca85S 	brand_ldb_get_dyns32
297628e3cbeSEdward Pilatowicz };
298