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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 #include <stdlib.h> 31 #include <stdio.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 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 47 48 void 49 rd_log(const int on_off) 50 { 51 (void) mutex_lock(&glob_mutex); 52 rtld_db_logging = on_off; 53 (void) mutex_unlock(&glob_mutex); 54 LOG(ps_plog(MSG_ORIG(MSG_DB_LOGENABLE))); 55 } 56 57 /* 58 * Versioning Notes. 59 * 60 * The following have been added as the versions of librtld_db 61 * have grown: 62 * 63 * RD_VERSION1: 64 * o baseline version 65 * 66 * RD_VERSION2: 67 * o added support for the use of the AT_SUN_LDBASE auxvector 68 * to find the initialial debugging (r_debug) structures 69 * in ld.so.1 70 * o added the rl_dynamic field to rd_loadobj_t 71 * o added the RD_FLG_MEM_OBJECT to be used with the 72 * rl_dynamic->rl_flags field. 73 * 74 * RD_VERSION3: 75 * o added the following fields/flags to the rd_plt_info_t 76 * type: 77 * pi_baddr - bound address of PLT (if bound) 78 * pi_flags - flag field 79 * RD_FLG_PI_PLTBOUND (flag for pi_flags) 80 * if set - the PLT is bound and pi_baddr 81 * is filled in with the destination of the PLT. 82 * 83 * RD_VERSION4: 84 * o added the following field to the rd_loadobj_t structure: 85 * rl_tlsmodid - module ID for TLS references 86 */ 87 rd_err_e 88 rd_init(int version) 89 { 90 if ((version < RD_VERSION1) || 91 (version > RD_VERSION)) 92 return (RD_NOCAPAB); 93 rtld_db_version = version; 94 LOG(ps_plog(MSG_ORIG(MSG_DB_RDINIT), rtld_db_version)); 95 return (RD_OK); 96 } 97 98 99 rd_err_e 100 rd_reset(struct rd_agent *rap) 101 { 102 rd_err_e err; 103 104 RDAGLOCK(rap); 105 106 rap->rd_flags = 0; 107 108 #ifdef _LP64 109 /* 110 * Determine if client is 32-bit or 64-bit. 111 */ 112 if (ps_pdmodel(rap->rd_psp, &rap->rd_dmodel) != PS_OK) { 113 LOG(ps_plog(MSG_ORIG(MSG_DB_DMLOOKFAIL))); 114 RDAGUNLOCK(rap); 115 return (RD_DBERR); 116 } 117 118 if (rap->rd_dmodel == PR_MODEL_LP64) 119 err = _rd_reset64(rap); 120 else 121 #endif 122 err = _rd_reset32(rap); 123 124 RDAGUNLOCK(rap); 125 return (err); 126 } 127 128 129 rd_agent_t * 130 rd_new(struct ps_prochandle *php) 131 { 132 rd_agent_t *rap; 133 134 LOG(ps_plog(MSG_ORIG(MSG_DB_RDNEW), php)); 135 if ((rap = (rd_agent_t *)calloc(sizeof (rd_agent_t), 1)) == NULL) 136 return (0); 137 138 rap->rd_psp = php; 139 (void) mutex_init(&rap->rd_mutex, USYNC_THREAD, 0); 140 if (rd_reset(rap) != RD_OK) { 141 free(rap); 142 LOG(ps_plog(MSG_ORIG(MSG_DB_RESETFAIL))); 143 return ((rd_agent_t *)0); 144 } 145 146 return (rap); 147 } 148 149 150 void 151 rd_delete(rd_agent_t *rap) 152 { 153 LOG(ps_plog(MSG_ORIG(MSG_DB_RDDELETE), rap)); 154 free(rap); 155 } 156 157 158 rd_err_e 159 rd_loadobj_iter(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 160 { 161 rd_err_e err; 162 163 RDAGLOCK(rap); 164 165 #ifdef _LP64 166 if (rap->rd_dmodel == PR_MODEL_LP64) 167 err = _rd_loadobj_iter64(rap, cb, client_data); 168 else 169 #endif 170 err = _rd_loadobj_iter32(rap, cb, client_data); 171 172 RDAGUNLOCK(rap); 173 return (err); 174 } 175 176 177 rd_err_e 178 rd_plt_resolution(rd_agent_t *rap, psaddr_t pc, lwpid_t lwpid, 179 psaddr_t pltbase, rd_plt_info_t *rpi) 180 { 181 rd_err_e err; 182 RDAGLOCK(rap); 183 #ifdef _LP64 184 if (rap->rd_dmodel == PR_MODEL_LP64) 185 err = plt64_resolution(rap, pc, lwpid, pltbase, 186 rpi); 187 else 188 #endif 189 err = plt32_resolution(rap, pc, lwpid, pltbase, 190 rpi); 191 RDAGUNLOCK(rap); 192 return (err); 193 } 194 195 rd_err_e 196 rd_event_addr(rd_agent_t *rap, rd_event_e num, rd_notify_t *np) 197 { 198 rd_err_e rc = RD_OK; 199 200 RDAGLOCK(rap); 201 switch (num) { 202 case RD_NONE: 203 break; 204 case RD_PREINIT: 205 np->type = RD_NOTIFY_BPT; 206 np->u.bptaddr = rap->rd_preinit; 207 break; 208 case RD_POSTINIT: 209 np->type = RD_NOTIFY_BPT; 210 np->u.bptaddr = rap->rd_postinit; 211 break; 212 case RD_DLACTIVITY: 213 np->type = RD_NOTIFY_BPT; 214 np->u.bptaddr = rap->rd_dlact; 215 break; 216 default: 217 LOG(ps_plog(MSG_ORIG(MSG_DB_UNEXPEVENT), num)); 218 rc = RD_ERR; 219 break; 220 } 221 if (rc == RD_OK) { 222 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTADDR), num, 223 EC_ADDR(np->u.bptaddr))); 224 } 225 226 RDAGUNLOCK(rap); 227 return (rc); 228 } 229 230 231 /* ARGSUSED 0 */ 232 rd_err_e 233 rd_event_enable(rd_agent_t *rap, int onoff) 234 { 235 rd_err_e err; 236 237 RDAGLOCK(rap); 238 239 #ifdef _LP64 240 if (rap->rd_dmodel == PR_MODEL_LP64) 241 err = _rd_event_enable64(rap, onoff); 242 else 243 #endif 244 err = _rd_event_enable32(rap, onoff); 245 246 RDAGUNLOCK(rap); 247 return (err); 248 } 249 250 251 rd_err_e 252 rd_event_getmsg(rd_agent_t *rap, rd_event_msg_t *emsg) 253 { 254 rd_err_e err; 255 256 RDAGLOCK(rap); 257 258 #ifdef _LP64 259 if (rap->rd_dmodel == PR_MODEL_LP64) 260 err = _rd_event_getmsg64(rap, emsg); 261 else 262 #endif 263 err = _rd_event_getmsg32(rap, emsg); 264 265 RDAGUNLOCK(rap); 266 return (err); 267 } 268 269 270 rd_err_e 271 rd_binder_exit_addr(struct rd_agent *rap, const char *bname, psaddr_t *beaddr) 272 { 273 ps_sym_t sym; 274 275 if (rap->rd_tbinder) { 276 *beaddr = rap->rd_tbinder; 277 return (RD_OK); 278 } 279 if (ps_pglobal_sym(rap->rd_psp, PS_OBJ_LDSO, bname, &sym) != PS_OK) { 280 LOG(ps_plog(MSG_ORIG(MSG_DB_UNFNDSYM), 281 bname)); 282 return (RD_ERR); 283 } 284 285 rap->rd_tbinder = *beaddr = sym.st_value + sym.st_size - M_BIND_ADJ; 286 287 return (RD_OK); 288 } 289 290 291 rd_err_e 292 rd_objpad_enable(struct rd_agent *rap, size_t padsize) 293 { 294 rd_err_e err; 295 296 RDAGLOCK(rap); 297 298 #ifdef _LP64 299 if (rap->rd_dmodel == PR_MODEL_LP64) 300 err = _rd_objpad_enable64(rap, padsize); 301 else 302 #endif 303 err = _rd_objpad_enable32(rap, padsize); 304 305 RDAGUNLOCK(rap); 306 return (err); 307 } 308 309 310 char * 311 rd_errstr(rd_err_e rderr) 312 { 313 /* 314 * Convert an 'rd_err_e' to a string 315 */ 316 switch (rderr) { 317 case RD_OK: 318 return ((char *)MSG_ORIG(MSG_ER_OK)); 319 case RD_ERR: 320 return ((char *)MSG_ORIG(MSG_ER_ERR)); 321 case RD_DBERR: 322 return ((char *)MSG_ORIG(MSG_ER_DBERR)); 323 case RD_NOCAPAB: 324 return ((char *)MSG_ORIG(MSG_ER_NOCAPAB)); 325 case RD_NODYNAM: 326 return ((char *)MSG_ORIG(MSG_ER_NODYNAM)); 327 case RD_NOBASE: 328 return ((char *)MSG_ORIG(MSG_ER_NOBASE)); 329 case RD_NOMAPS: 330 return ((char *)MSG_ORIG(MSG_ER_NOMAPS)); 331 default: 332 return ((char *)MSG_ORIG(MSG_ER_DEFAULT)); 333 } 334 } 335