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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <string.h> 32 #include <proc_service.h> 33 #include <link.h> 34 #include <rtld_db.h> 35 #include <rtld.h> 36 #include <_rtld_db.h> 37 #include <msg.h> 38 #include <sys/param.h> 39 40 /* 41 * Mutex to protect global data 42 */ 43 mutex_t glob_mutex = DEFAULTMUTEX; 44 int rtld_db_version = RD_VERSION1; 45 int rtld_db_logging = 0; 46 char rtld_db_helper_path[MAXPATHLEN]; 47 48 49 void 50 rd_log(const int on_off) 51 { 52 (void) mutex_lock(&glob_mutex); 53 rtld_db_logging = on_off; 54 (void) mutex_unlock(&glob_mutex); 55 LOG(ps_plog(MSG_ORIG(MSG_DB_LOGENABLE))); 56 } 57 58 /* 59 * Versioning Notes. 60 * 61 * The following have been added as the versions of librtld_db 62 * have grown: 63 * 64 * RD_VERSION1: 65 * o baseline version 66 * 67 * RD_VERSION2: 68 * o added support for the use of the AT_SUN_LDBASE auxvector 69 * to find the initialial debugging (r_debug) structures 70 * in ld.so.1 71 * o added the rl_dynamic field to rd_loadobj_t 72 * o added the RD_FLG_MEM_OBJECT to be used with the 73 * rl_dynamic->rl_flags field. 74 * 75 * RD_VERSION3: 76 * o added the following fields/flags to the rd_plt_info_t 77 * type: 78 * pi_baddr - bound address of PLT (if bound) 79 * pi_flags - flag field 80 * RD_FLG_PI_PLTBOUND (flag for pi_flags) 81 * if set - the PLT is bound and pi_baddr 82 * is filled in with the destination of the PLT. 83 * 84 * RD_VERSION4: 85 * o added the following field to the rd_loadobj_t structure: 86 * rl_tlsmodid - module ID for TLS references 87 */ 88 rd_err_e 89 rd_init(int version) 90 { 91 if ((version < RD_VERSION1) || 92 (version > RD_VERSION)) 93 return (RD_NOCAPAB); 94 rtld_db_version = version; 95 LOG(ps_plog(MSG_ORIG(MSG_DB_RDINIT), rtld_db_version)); 96 97 return (RD_OK); 98 } 99 100 rd_err_e 101 rd_ctl(int cmd, void *arg) 102 { 103 if (cmd != RD_CTL_SET_HELPPATH || arg == NULL || 104 strlen((char *)arg) >= MAXPATHLEN) 105 return (RD_ERR); 106 107 (void) strcpy(rtld_db_helper_path, (char *)arg); 108 109 return (RD_OK); 110 } 111 112 rd_err_e 113 rd_get_dyns(rd_agent_t *rap, psaddr_t addr, void **dynpp, size_t *dynpp_sz) 114 { 115 if (rap->rd_helper.rh_ops != NULL) 116 return (rap->rd_helper.rh_ops->rho_get_dyns( 117 rap->rd_helper.rh_data, addr, dynpp, dynpp_sz)); 118 119 #ifdef _LP64 120 if (rap->rd_dmodel == PR_MODEL_LP64) 121 return (_rd_get_dyns64(rap, 122 addr, (Elf64_Dyn **)dynpp, dynpp_sz)); 123 else 124 #endif 125 return (_rd_get_dyns32(rap, 126 addr, (Dyn **)dynpp, dynpp_sz)); 127 } 128 129 rd_err_e 130 rd_reset(struct rd_agent *rap) 131 { 132 rd_err_e err; 133 134 RDAGLOCK(rap); 135 136 rap->rd_flags = 0; 137 138 #ifdef _LP64 139 /* 140 * Determine if client is 32-bit or 64-bit. 141 */ 142 if (ps_pdmodel(rap->rd_psp, &rap->rd_dmodel) != PS_OK) { 143 LOG(ps_plog(MSG_ORIG(MSG_DB_DMLOOKFAIL))); 144 RDAGUNLOCK(rap); 145 return (RD_DBERR); 146 } 147 148 if (rap->rd_dmodel == PR_MODEL_LP64) 149 err = _rd_reset64(rap); 150 else 151 #endif 152 err = _rd_reset32(rap); 153 154 RDAGUNLOCK(rap); 155 return (err); 156 } 157 158 159 rd_agent_t * 160 rd_new(struct ps_prochandle *php) 161 { 162 rd_agent_t *rap; 163 164 LOG(ps_plog(MSG_ORIG(MSG_DB_RDNEW), php)); 165 if ((rap = (rd_agent_t *)calloc(sizeof (rd_agent_t), 1)) == NULL) 166 return (0); 167 168 rap->rd_psp = php; 169 (void) mutex_init(&rap->rd_mutex, USYNC_THREAD, 0); 170 if (rd_reset(rap) != RD_OK) { 171 if (rap->rd_helper.rh_dlhandle != NULL) { 172 rap->rd_helper.rh_ops->rho_fini(rap->rd_helper.rh_data); 173 (void) dlclose(rap->rd_helper.rh_dlhandle); 174 } 175 free(rap); 176 LOG(ps_plog(MSG_ORIG(MSG_DB_RESETFAIL))); 177 return ((rd_agent_t *)0); 178 } 179 180 return (rap); 181 } 182 183 184 void 185 rd_delete(rd_agent_t *rap) 186 { 187 LOG(ps_plog(MSG_ORIG(MSG_DB_RDDELETE), rap)); 188 if (rap->rd_helper.rh_dlhandle != NULL) { 189 rap->rd_helper.rh_ops->rho_fini(rap->rd_helper.rh_data); 190 (void) dlclose(rap->rd_helper.rh_dlhandle); 191 } 192 free(rap); 193 } 194 195 196 rd_err_e 197 rd_loadobj_iter(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 198 { 199 rd_err_e err; 200 201 RDAGLOCK(rap); 202 203 #ifdef _LP64 204 if (rap->rd_dmodel == PR_MODEL_LP64) 205 err = _rd_loadobj_iter64(rap, cb, client_data); 206 else 207 #endif 208 err = _rd_loadobj_iter32(rap, cb, client_data); 209 210 RDAGUNLOCK(rap); 211 return (err); 212 } 213 214 215 rd_err_e 216 rd_plt_resolution(rd_agent_t *rap, psaddr_t pc, lwpid_t lwpid, 217 psaddr_t pltbase, rd_plt_info_t *rpi) 218 { 219 rd_err_e err; 220 RDAGLOCK(rap); 221 #ifdef _LP64 222 if (rap->rd_dmodel == PR_MODEL_LP64) 223 err = plt64_resolution(rap, pc, lwpid, pltbase, 224 rpi); 225 else 226 #endif 227 err = plt32_resolution(rap, pc, lwpid, pltbase, 228 rpi); 229 RDAGUNLOCK(rap); 230 return (err); 231 } 232 233 rd_err_e 234 rd_event_addr(rd_agent_t *rap, rd_event_e num, rd_notify_t *np) 235 { 236 rd_err_e rc = RD_OK; 237 238 RDAGLOCK(rap); 239 switch (num) { 240 case RD_NONE: 241 break; 242 case RD_PREINIT: 243 np->type = RD_NOTIFY_BPT; 244 np->u.bptaddr = rap->rd_preinit; 245 break; 246 case RD_POSTINIT: 247 np->type = RD_NOTIFY_BPT; 248 np->u.bptaddr = rap->rd_postinit; 249 break; 250 case RD_DLACTIVITY: 251 np->type = RD_NOTIFY_BPT; 252 np->u.bptaddr = rap->rd_dlact; 253 break; 254 default: 255 LOG(ps_plog(MSG_ORIG(MSG_DB_UNEXPEVENT), num)); 256 rc = RD_ERR; 257 break; 258 } 259 if (rc == RD_OK) { 260 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTADDR), num, 261 EC_ADDR(np->u.bptaddr))); 262 } 263 264 RDAGUNLOCK(rap); 265 return (rc); 266 } 267 268 269 /* ARGSUSED 0 */ 270 rd_err_e 271 rd_event_enable(rd_agent_t *rap, int onoff) 272 { 273 rd_err_e err; 274 275 RDAGLOCK(rap); 276 277 #ifdef _LP64 278 if (rap->rd_dmodel == PR_MODEL_LP64) 279 err = _rd_event_enable64(rap, onoff); 280 else 281 #endif 282 err = _rd_event_enable32(rap, onoff); 283 284 RDAGUNLOCK(rap); 285 return (err); 286 } 287 288 289 rd_err_e 290 rd_event_getmsg(rd_agent_t *rap, rd_event_msg_t *emsg) 291 { 292 rd_err_e err; 293 294 RDAGLOCK(rap); 295 296 #ifdef _LP64 297 if (rap->rd_dmodel == PR_MODEL_LP64) 298 err = _rd_event_getmsg64(rap, emsg); 299 else 300 #endif 301 err = _rd_event_getmsg32(rap, emsg); 302 303 RDAGUNLOCK(rap); 304 return (err); 305 } 306 307 308 rd_err_e 309 rd_binder_exit_addr(struct rd_agent *rap, const char *bname, psaddr_t *beaddr) 310 { 311 ps_sym_t sym; 312 313 if (rap->rd_tbinder) { 314 *beaddr = rap->rd_tbinder; 315 return (RD_OK); 316 } 317 if (ps_pglobal_sym(rap->rd_psp, PS_OBJ_LDSO, bname, &sym) != PS_OK) { 318 LOG(ps_plog(MSG_ORIG(MSG_DB_UNFNDSYM), 319 bname)); 320 return (RD_ERR); 321 } 322 323 rap->rd_tbinder = *beaddr = sym.st_value + sym.st_size - M_BIND_ADJ; 324 325 return (RD_OK); 326 } 327 328 329 rd_err_e 330 rd_objpad_enable(struct rd_agent *rap, size_t padsize) 331 { 332 rd_err_e err; 333 334 RDAGLOCK(rap); 335 336 #ifdef _LP64 337 if (rap->rd_dmodel == PR_MODEL_LP64) 338 err = _rd_objpad_enable64(rap, padsize); 339 else 340 #endif 341 err = _rd_objpad_enable32(rap, padsize); 342 343 RDAGUNLOCK(rap); 344 return (err); 345 } 346 347 348 char * 349 rd_errstr(rd_err_e rderr) 350 { 351 /* 352 * Convert an 'rd_err_e' to a string 353 */ 354 switch (rderr) { 355 case RD_OK: 356 return ((char *)MSG_ORIG(MSG_ER_OK)); 357 case RD_ERR: 358 return ((char *)MSG_ORIG(MSG_ER_ERR)); 359 case RD_DBERR: 360 return ((char *)MSG_ORIG(MSG_ER_DBERR)); 361 case RD_NOCAPAB: 362 return ((char *)MSG_ORIG(MSG_ER_NOCAPAB)); 363 case RD_NODYNAM: 364 return ((char *)MSG_ORIG(MSG_ER_NODYNAM)); 365 case RD_NOBASE: 366 return ((char *)MSG_ORIG(MSG_ER_NOBASE)); 367 case RD_NOMAPS: 368 return ((char *)MSG_ORIG(MSG_ER_NOMAPS)); 369 default: 370 return ((char *)MSG_ORIG(MSG_ER_DEFAULT)); 371 } 372 }