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