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