1*80e2ca85S /*
2*80e2ca85S * CDDL HEADER START
3*80e2ca85S *
4*80e2ca85S * The contents of this file are subject to the terms of the
5*80e2ca85S * Common Development and Distribution License (the "License").
6*80e2ca85S * You may not use this file except in compliance with the License.
7*80e2ca85S *
8*80e2ca85S * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*80e2ca85S * or http://www.opensolaris.org/os/licensing.
10*80e2ca85S * See the License for the specific language governing permissions
11*80e2ca85S * and limitations under the License.
12*80e2ca85S *
13*80e2ca85S * When distributing Covered Code, include this CDDL HEADER in each
14*80e2ca85S * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*80e2ca85S * If applicable, add the following below this CDDL HEADER, with the
16*80e2ca85S * fields enclosed by brackets "[]" replaced with your own identifying
17*80e2ca85S * information: Portions Copyright [yyyy] [name of copyright owner]
18*80e2ca85S *
19*80e2ca85S * CDDL HEADER END
20*80e2ca85S */
21*80e2ca85S
22*80e2ca85S /*
23*80e2ca85S * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*80e2ca85S */
25*80e2ca85S
26*80e2ca85S #include <assert.h>
27*80e2ca85S #include <stdio.h>
28*80e2ca85S #include <stdlib.h>
29*80e2ca85S #include <string.h>
30*80e2ca85S #include <strings.h>
31*80e2ca85S #include <libproc.h>
32*80e2ca85S #include <proc_service.h>
33*80e2ca85S #include <synch.h>
34*80e2ca85S #include <sys/types.h>
35*80e2ca85S #include <sys/link.h>
36*80e2ca85S #include <rtld_db.h>
37*80e2ca85S #include <sys/brand.h>
38*80e2ca85S
39*80e2ca85S /*
40*80e2ca85S * ATTENTION:
41*80e2ca85S * Librtl_db brand plugin libraries should NOT directly invoke any
42*80e2ca85S * libproc.so interfaces or be linked against libproc. If a librtl_db
43*80e2ca85S * brand plugin library uses libproc.so interfaces then it may break
44*80e2ca85S * any other librtld_db consumers (like mdb) that tries to attach
45*80e2ca85S * to a branded process. The only safe interfaces that the a librtld_db
46*80e2ca85S * brand plugin library can use to access a target process are the
47*80e2ca85S * proc_service(3PROC) apis.
48*80e2ca85S */
49*80e2ca85S
50*80e2ca85S /*
51*80e2ca85S * M_DATA comes from some streams header file but is also redifined in
52*80e2ca85S * _rtld_db.h, so nuke the old streams definition here.
53*80e2ca85S */
54*80e2ca85S #ifdef M_DATA
55*80e2ca85S #undef M_DATA
56*80e2ca85S #endif /* M_DATA */
57*80e2ca85S
58*80e2ca85S /*
59*80e2ca85S * For 32-bit versions of this library, this file get's compiled once.
60*80e2ca85S * For 64-bit versions of this library, this file get's compiled twice,
61*80e2ca85S * once with _ELF64 defined and once without. The expectation is that
62*80e2ca85S * the 64-bit version of the library can properly deal with both 32-bit
63*80e2ca85S * and 64-bit elf files, hence in the 64-bit library there are two copies
64*80e2ca85S * of all the interfaces in this file, one set named *32 and one named *64.
65*80e2ca85S *
66*80e2ca85S * This also means that we need to be careful when declaring local pointers
67*80e2ca85S * that point to objects in another processes address space, since these
68*80e2ca85S * pointers may not match the current processes pointer width. Basically,
69*80e2ca85S * we should not use any objects that change size between 32 and 64 bit
70*80e2ca85S * modes like: long, void *, uintprt_t, caddr_t, psaddr_t, size_t, etc.
71*80e2ca85S * Instead we should declare all pointers as uint32_t. Then when we
72*80e2ca85S * are compiled to deal with 64-bit targets we'll re-define uing32_t
73*80e2ca85S * to be a uint64_t.
74*80e2ca85S */
75*80e2ca85S #ifdef _LP64
76*80e2ca85S #ifdef _ELF64
77*80e2ca85S #define uint32_t uint64_t
78*80e2ca85S #define Elf32_Dyn Elf64_Dyn
79*80e2ca85S #define validate_rdebug32 validate_rdebug64
80*80e2ca85S #define _rd_loadobj_iter32 _rd_loadobj_iter64
81*80e2ca85S #define _rd_get_dyns32 _rd_get_dyns64
82*80e2ca85S #define dummy_ldb32 dummy_ldb64
83*80e2ca85S #define dummy_ldb_init32 dummy_ldb_init64
84*80e2ca85S #define dummy_ldb_fini32 dummy_ldb_fini64
85*80e2ca85S #define dummy_ldb_loadobj_iter32 dummy_ldb_loadobj_iter64
86*80e2ca85S #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
91*80e2ca85S #endif /* _ELF64 */
92*80e2ca85S #endif /* _LP64 */
93*80e2ca85S
94*80e2ca85S /* Included from usr/src/cmd/sgs/librtld_db/common */
95*80e2ca85S #include <_rtld_db.h>
96*80e2ca85S
97*80e2ca85S /*ARGSUSED*/
98*80e2ca85S static rd_helper_data_t
dummy_ldb_init32(rd_agent_t * rap,struct ps_prochandle * php)99*80e2ca85S dummy_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php)
100*80e2ca85S {
101*80e2ca85S return (NULL);
102*80e2ca85S }
103*80e2ca85S
104*80e2ca85S /*ARGSUSED*/
105*80e2ca85S static void
dummy_ldb_fini32(rd_helper_data_t rhd)106*80e2ca85S dummy_ldb_fini32(rd_helper_data_t rhd)
107*80e2ca85S {
108*80e2ca85S }
109*80e2ca85S
110*80e2ca85S /*ARGSUSED*/
111*80e2ca85S static int
dummy_ldb_loadobj_iter32(rd_helper_data_t rhd,rl_iter_f * cb,void * client_data)112*80e2ca85S dummy_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data)
113*80e2ca85S {
114*80e2ca85S return (RD_OK);
115*80e2ca85S }
116*80e2ca85S
117*80e2ca85S /*ARGSUSED*/
118*80e2ca85S static rd_err_e
dummy_ldb_get_dyns32(rd_helper_data_t rhd,psaddr_t addr,void ** dynpp,size_t * dynpp_sz)119*80e2ca85S dummy_ldb_get_dyns32(rd_helper_data_t rhd,
120*80e2ca85S psaddr_t addr, void **dynpp, size_t *dynpp_sz)
121*80e2ca85S {
122*80e2ca85S *dynpp = NULL;
123*80e2ca85S *dynpp_sz = 0;
124*80e2ca85S return (RD_OK);
125*80e2ca85S }
126*80e2ca85S
127*80e2ca85S static rd_helper_ops_t dummy_ldb32 = {
128*80e2ca85S LM_ID_BRAND,
129*80e2ca85S dummy_ldb_init32,
130*80e2ca85S dummy_ldb_fini32,
131*80e2ca85S dummy_ldb_loadobj_iter32,
132*80e2ca85S dummy_ldb_get_dyns32
133*80e2ca85S };
134*80e2ca85S
135*80e2ca85S static uint32_t
brand_ldb_getauxval32(struct ps_prochandle * php,int type)136*80e2ca85S brand_ldb_getauxval32(struct ps_prochandle *php, int type)
137*80e2ca85S {
138*80e2ca85S const auxv_t *auxvp = NULL;
139*80e2ca85S
140*80e2ca85S if (ps_pauxv(php, &auxvp) != PS_OK)
141*80e2ca85S return ((uint32_t)-1);
142*80e2ca85S
143*80e2ca85S while (auxvp->a_type != AT_NULL) {
144*80e2ca85S if (auxvp->a_type == type)
145*80e2ca85S return ((uint32_t)(uintptr_t)auxvp->a_un.a_ptr);
146*80e2ca85S auxvp++;
147*80e2ca85S }
148*80e2ca85S return ((uint32_t)-1);
149*80e2ca85S }
150*80e2ca85S
151*80e2ca85S /*
152*80e2ca85S * Normally, the native Solaris librtldb_db plugin uses a bunch of different
153*80e2ca85S * methods to try and find the rdebug structure associated with the target
154*80e2ca85S * process we're debugging. For details on the different methods see
155*80e2ca85S * _rd_reset32(). Thankfully our job is easier. We know that the brand
156*80e2ca85S * library is always linked against the native linker, and when the
157*80e2ca85S * process was first executed we saved off a pointer to the brand linkers
158*80e2ca85S * 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.
160*80e2ca85S */
161*80e2ca85S /*ARGSUSED*/
162*80e2ca85S 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)
164*80e2ca85S {
165*80e2ca85S struct rd_agent *rap_new;
166*80e2ca85S uint32_t lddata_addr;
167*80e2ca85S int rd_dmodel;
168*80e2ca85S
169*80e2ca85S if (ps_pdmodel(php, &rd_dmodel) != PS_OK) {
170*80e2ca85S ps_plog("brand_ldb_init: lookup of data model failed");
171*80e2ca85S return (NULL);
172*80e2ca85S }
173*80e2ca85S #ifdef _ELF64
174*80e2ca85S assert(rd_dmodel == PR_MODEL_LP64);
175*80e2ca85S #else /* !_ELF64 */
176*80e2ca85S assert(rd_dmodel == PR_MODEL_ILP32);
177*80e2ca85S #endif /* !_ELF64 */
178*80e2ca85S
179*80e2ca85S lddata_addr = brand_ldb_getauxval32(php, AT_SUN_BRAND_COMMON_LDDATA);
180*80e2ca85S if (lddata_addr == (uint32_t)-1) {
181*80e2ca85S ps_plog("brand_ldb_init: no LDDATA found in aux vector");
182*80e2ca85S return (NULL);
183*80e2ca85S }
184*80e2ca85S ps_plog("brand_ldb_init: found LDDATA auxv ld.so.1 data seg "
185*80e2ca85S "at: 0x%p", lddata_addr);
186*80e2ca85S
187*80e2ca85S /*
188*80e2ca85S * Ok. So this is kinda ugly. Basically we know that we're going to
189*80e2ca85S * be parsing data from link maps that are generated by a Solaris
190*80e2ca85S * linker. As it turns out, that's exactly what the default
191*80e2ca85S * Solaris librtld_db library is designed to do. So rather than
192*80e2ca85S * duplicate all that link map parsing code here we'll simply
193*80e2ca85S * invoke the native librtld_db that normally does this, and when
194*80e2ca85S * we do we'll point them at our emulation libraries link map.
195*80e2ca85S *
196*80e2ca85S * Of course these interfacess aren't really public interfaces
197*80e2ca85S * and they take a "struct rd_agent" as a parameter. So here
198*80e2ca85S * we'll allocate and initialize a new "struct rd_agent", point
199*80e2ca85S * it at our emulation libraries link map, and initialize just
200*80e2ca85S * enough of the structure to make the librtld_db interfaces
201*80e2ca85S * that we want to use happy.
202*80e2ca85S */
203*80e2ca85S if ((rap_new = calloc(sizeof (*rap_new), 1)) == NULL) {
204*80e2ca85S ps_plog("brand_ldb_init: can't allocate memory");
205*80e2ca85S return (NULL);
206*80e2ca85S }
207*80e2ca85S rap_new->rd_dmodel = rd_dmodel;
208*80e2ca85S rap_new->rd_psp = php;
209*80e2ca85S rap_new->rd_rdebug = lddata_addr;
210*80e2ca85S (void) mutex_init(&rap_new->rd_mutex, USYNC_THREAD, 0);
211*80e2ca85S
212*80e2ca85S /*
213*80e2ca85S * When we get invoked from librtld_db, and we call back into it,
214*80e2ca85S * librtld_db will once again check if there is a plugin and
215*80e2ca85S * invoke it. Since we don't want to enter a recursive loop
216*80e2ca85S * we're going to specify a different plugin interface for
217*80e2ca85S * our linkmap, and these new plugin interfaces won't actually
218*80e2ca85S * do anything other than return.
219*80e2ca85S */
220*80e2ca85S rap_new->rd_helper.rh_ops = &dummy_ldb32;
221*80e2ca85S
222*80e2ca85S /*
223*80e2ca85S * validate_rdebug32() requires the following "struct rd_agent"
224*80e2ca85S * members to be initialized:
225*80e2ca85S * rd_psp, rd_rdebug
226*80e2ca85S *
227*80e2ca85S * validate_rdebug32() initializes the following "struct rd_agent"
228*80e2ca85S * members:
229*80e2ca85S * rd_flags, rd_rdebugvers, rd_rtlddbpriv
230*80e2ca85S */
231*80e2ca85S if (validate_rdebug32(rap_new) != RD_OK) {
232*80e2ca85S ps_plog("brand_ldb_init: can't find valid r_debug data");
233*80e2ca85S free(rap_new);
234*80e2ca85S return (NULL);
235*80e2ca85S }
236*80e2ca85S
237*80e2ca85S ps_plog("brand_ldb_init: finished, helper_data=0x%p", rap_new);
238*80e2ca85S return ((rd_helper_data_t)rap_new);
239*80e2ca85S }
240*80e2ca85S
241*80e2ca85S static void
brand_ldb_fini32(rd_helper_data_t rhd)242*80e2ca85S brand_ldb_fini32(rd_helper_data_t rhd)
243*80e2ca85S {
244*80e2ca85S struct rd_agent *rap = (struct rd_agent *)rhd;
245*80e2ca85S ps_plog("brand_ldb_fini: cleaning up brand helper");
246*80e2ca85S free(rap);
247*80e2ca85S }
248*80e2ca85S
249*80e2ca85S /*ARGSUSED*/
250*80e2ca85S 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)
252*80e2ca85S {
253*80e2ca85S struct rd_agent *rap = (struct rd_agent *)rhd;
254*80e2ca85S int err;
255*80e2ca85S
256*80e2ca85S ps_plog("brand_ldb_loadobj_iter(helper_data=0x%p)", rhd);
257*80e2ca85S assert(rap->rd_psp == php);
258*80e2ca85S RDAGLOCK(rap);
259*80e2ca85S /*
260*80e2ca85S * _rd_loadobj_iter32() requires the following "struct rd_agent"
261*80e2ca85S * members to be initialized:
262*80e2ca85S * rd_rtlddbpriv, rd_rdebugvers, rd_flags,
263*80e2ca85S * rd_helper.rh_ops, rd_dmodel
264*80e2ca85S */
265*80e2ca85S err = _rd_loadobj_iter32(rap, cb, client_data);
266*80e2ca85S RDAGUNLOCK(rap);
267*80e2ca85S ps_plog("brand_ldb_loadobj_iter: finished, err = %d", err);
268*80e2ca85S return (err);
269*80e2ca85S }
270*80e2ca85S
271*80e2ca85S /*ARGSUSED*/
272*80e2ca85S 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,
274*80e2ca85S psaddr_t addr, void **dynpp, size_t *dynpp_sz)
275*80e2ca85S {
276*80e2ca85S struct rd_agent *rap = (struct rd_agent *)rhd;
277*80e2ca85S int err;
278*80e2ca85S
279*80e2ca85S ps_plog("brand_ldb_get_dyns(helper_data=0x%p)", rhd);
280*80e2ca85S err = _rd_get_dyns32(rap, addr, (Elf32_Dyn **)dynpp, dynpp_sz);
281*80e2ca85S ps_plog("brand_ldb_get_dyns: finished, err = %d", err);
282*80e2ca85S return (err);
283*80e2ca85S }
284*80e2ca85S
285*80e2ca85S /*
286*80e2ca85S * Librtld_db plugin linkage struct.
287*80e2ca85S *
288*80e2ca85S * When we get loaded by librtld_db, it will look for the symbol below
289*80e2ca85S * to find our plugin entry points.
290*80e2ca85S */
291*80e2ca85S rd_helper_ops_t RTLD_DB_BRAND_OPS = {
292*80e2ca85S 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
297*80e2ca85S };
298