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 #include <stdlib.h> 30 #include <stdio.h> 31 #include <proc_service.h> 32 #include <link.h> 33 #include <rtld_db.h> 34 #include <rtld.h> 35 #include <_rtld_db.h> 36 #include <msg.h> 37 38 39 /* 40 * 64-bit builds are going to compile this module twice, the 41 * second time with _ELF64 defined. These defines should make 42 * all the necessary adjustments to the code. 43 */ 44 #ifdef _LP64 45 #ifdef _ELF64 46 #define _rd_reset32 _rd_reset64 47 #define _rd_event_enable32 _rd_event_enable64 48 #define _rd_event_getmsg32 _rd_event_getmsg64 49 #define _rd_objpad_enable32 _rd_objpad_enable64 50 #define _rd_loadobj_iter32 _rd_loadobj_iter64 51 #define find_dynamic_ent32 find_dynamic_ent64 52 #define TList List 53 #define TListnode Listnode 54 #else /* ELF32 */ 55 #define Rt_map Rt_map32 56 #define Rtld_db_priv Rtld_db_priv32 57 #define TList List32 58 #define TListnode Listnode32 59 #define Lm_list Lm_list32 60 #endif /* _ELF64 */ 61 #else /* _LP64 */ 62 #define TList List 63 #define TListnode Listnode 64 #endif /* _LP64 */ 65 66 67 static rd_err_e 68 validate_rdebug(struct rd_agent *rap) 69 { 70 struct ps_prochandle *php = rap->rd_psp; 71 psaddr_t db_privp; 72 Rtld_db_priv db_priv; 73 74 if (rap->rd_rdebug == 0) 75 return (RD_ERR); 76 /* 77 * The rtld_db_priv structure contains both the traditional (exposed) 78 * r_debug structure as well as private data only available to 79 * this library. 80 */ 81 db_privp = rap->rd_rdebug; 82 83 /* 84 * Verify that librtld_db & rtld are at the proper revision 85 * levels. 86 */ 87 if (ps_pread(php, db_privp, (char *)&db_priv, 88 sizeof (Rtld_db_priv)) != PS_OK) { 89 LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1), 90 EC_ADDR(db_privp))); 91 return (RD_DBERR); 92 } 93 94 if ((db_priv.rtd_version < R_RTLDDB_VERSION1) || 95 (db_priv.rtd_version > R_RTLDDB_VERSION)) { 96 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 97 db_priv.rtd_version, R_RTLDDB_VERSION)); 98 return (RD_NOCAPAB); 99 } 100 101 /* 102 * Is the image being examined from a core file or not. 103 * If it is a core file then the following write will fail. 104 */ 105 if (ps_pwrite(php, db_privp, (char *)&db_priv, 106 sizeof (Rtld_db_priv)) != PS_OK) 107 rap->rd_flags |= RDF_FL_COREFILE; 108 109 /* 110 * If this *is not* a core file then rtld_db & ld.so.1 are 111 * considered tightly coupled. If the versions of our private 112 * data structures don't match - fail! 113 */ 114 if (((rap->rd_flags & RDF_FL_COREFILE) == 0) && 115 (db_priv.rtd_version != R_RTLDDB_VERSION)) { 116 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 117 db_priv.rtd_version, R_RTLDDB_VERSION)); 118 return (RD_NOCAPAB); 119 } 120 121 rap->rd_rdebugvers = db_priv.rtd_version; 122 rap->rd_rtlddbpriv = db_privp; 123 124 LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug), 125 R_RTLDDB_VERSION, rap->rd_rdebugvers, 126 rap->rd_flags & RDF_FL_COREFILE)); 127 return (RD_OK); 128 } 129 130 131 rd_err_e 132 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr, 133 Xword dyntag, Dyn *dyn) 134 { 135 struct ps_prochandle *php = rap->rd_psp; 136 Dyn d; 137 138 d.d_tag = DT_NULL; 139 do { 140 if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) != 141 PS_OK) { 142 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4), 143 EC_ADDR(dynaddr))); 144 return (RD_DBERR); 145 } 146 dynaddr += sizeof (d); 147 if (d.d_tag == dyntag) 148 break; 149 } while (d.d_tag != DT_NULL); 150 if (d.d_tag == dyntag) { 151 *dyn = d; 152 LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag), 153 EC_ADDR(d.d_un.d_val))); 154 return (RD_OK); 155 } 156 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag))); 157 return (RD_DBERR); 158 } 159 160 rd_err_e 161 _rd_reset32(struct rd_agent *rap) 162 { 163 psaddr_t symaddr; 164 struct ps_prochandle *php = rap->rd_psp; 165 const auxv_t *auxvp = NULL; 166 rd_err_e rc = RD_OK; 167 168 /* 169 * librtld_db attempts three different methods to find 170 * the r_debug structure which is required to 171 * initialize itself. The methods are: 172 * method1: 173 * entirely independent of any text segment 174 * and relies on the AT_SUN_LDDATA auxvector 175 * to find the ld.so.1::rdebug structure. 176 * method2: 177 * lookup symbols in ld.so.1's symbol table 178 * to find the r_debug symbol. 179 * method3: 180 * (old dbx method) dependent upon the 181 * text segment/symbol table of the 182 * executable and not ld.so.1. We lookup the 183 * _DYNAMIC symbol in the executable and look for 184 * the DT_DEBUG entry in the .dynamic table. This 185 * points to rdebug. 186 * 187 * If none of that works - we fail. 188 */ 189 LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel)); 190 /* 191 * Method1 192 * 193 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA 194 */ 195 if (ps_pauxv(php, &auxvp) != PS_OK) { 196 LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV))); 197 rc = RD_ERR; 198 } 199 200 rap->rd_rdebug = 0; 201 202 if (auxvp != NULL) { 203 rc = RD_ERR; 204 while (auxvp->a_type != AT_NULL) { 205 if (auxvp->a_type == AT_SUN_LDDATA) { 206 /* LINTED */ 207 rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr; 208 LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA), 209 rap->rd_rdebug)); 210 rc = validate_rdebug(rap); 211 break; 212 } 213 auxvp++; 214 } 215 } 216 217 /* 218 * method2 - look for r_rdebug symbol in ld.so.1 219 */ 220 if (rc != RD_OK) { 221 /* 222 * If the AT_SUN_LDDATA auxv vector is not present 223 * fall back on doing a symlookup of 224 * the r_debug symbol. This is for backward 225 * compatiblity with older OS's 226 */ 227 LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA))); 228 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG), 229 &symaddr) != PS_OK) { 230 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 231 MSG_ORIG(MSG_SYM_DEBUG))); 232 rc = RD_DBERR; 233 } else { 234 rap->rd_rdebug = symaddr; 235 LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG), 236 EC_ADDR(symaddr))); 237 rc = validate_rdebug(rap); 238 } 239 } 240 241 242 /* 243 * method3 - find DT_DEBUG in the executables .dynamic section. 244 */ 245 if (rc != RD_OK) { 246 Dyn dyn; 247 if (ps_pglobal_lookup(php, PS_OBJ_EXEC, 248 MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) { 249 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC))); 250 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 251 return (rc); 252 } 253 rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn); 254 if (rc != RD_OK) { 255 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 256 return (rc); 257 } 258 rap->rd_rdebug = dyn.d_un.d_ptr; 259 rc = validate_rdebug(rap); 260 if (rc != RD_OK) { 261 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 262 return (rc); 263 } 264 } 265 266 if ((rap->rd_flags & RDF_FL_COREFILE) == 0) { 267 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 268 MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) { 269 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 270 MSG_ORIG(MSG_SYM_PREINIT))); 271 return (RD_DBERR); 272 } 273 rap->rd_preinit = symaddr; 274 275 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 276 MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) { 277 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 278 MSG_ORIG(MSG_SYM_POSTINIT))); 279 return (RD_DBERR); 280 } 281 rap->rd_postinit = symaddr; 282 283 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 284 MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) { 285 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 286 MSG_ORIG(MSG_SYM_DLACT))); 287 return (RD_DBERR); 288 } 289 rap->rd_dlact = symaddr; 290 rap->rd_tbinder = 0; 291 } 292 293 return (RD_OK); 294 } 295 296 297 rd_err_e 298 _rd_event_enable32(rd_agent_t *rap, int onoff) 299 { 300 struct ps_prochandle *php = rap->rd_psp; 301 Rtld_db_priv rdb; 302 303 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff)); 304 /* 305 * Tell the debugged process that debugging is occuring 306 * This will enable the storing of event messages so that 307 * the can be gathered by the debugger. 308 */ 309 if (ps_pread(php, rap->rd_rdebug, (char *)&rdb, 310 sizeof (Rtld_db_priv)) != PS_OK) { 311 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1), 312 EC_ADDR((uintptr_t)&rdb))); 313 return (RD_DBERR); 314 } 315 316 if (onoff) 317 rdb.rtd_rdebug.r_flags |= RD_FL_DBG; 318 else 319 rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG; 320 321 if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb, 322 sizeof (Rtld_db_priv)) != PS_OK) { 323 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1), 324 EC_ADDR((uintptr_t)&rdb))); 325 return (RD_DBERR); 326 } 327 328 return (RD_OK); 329 } 330 331 332 rd_err_e 333 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg) 334 { 335 Rtld_db_priv rdb; 336 337 if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb, 338 sizeof (Rtld_db_priv)) != PS_OK) { 339 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2), 340 EC_ADDR(rap->rd_rdebug))); 341 return (RD_DBERR); 342 } 343 emsg->type = rdb.rtd_rdebug.r_rdevent; 344 if (emsg->type == RD_DLACTIVITY) { 345 switch (rdb.rtd_rdebug.r_state) { 346 case RT_CONSISTENT: 347 emsg->u.state = RD_CONSISTENT; 348 break; 349 case RT_ADD: 350 emsg->u.state = RD_ADD; 351 break; 352 case RT_DELETE: 353 emsg->u.state = RD_DELETE; 354 break; 355 } 356 } else 357 emsg->u.state = RD_NOSTATE; 358 359 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel, 360 emsg->type, emsg->u.state)); 361 362 return (RD_OK); 363 } 364 365 366 rd_err_e 367 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize) 368 { 369 Rtld_db_priv db_priv; 370 struct ps_prochandle *php = rap->rd_psp; 371 372 LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize))); 373 374 if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv, 375 sizeof (Rtld_db_priv)) != PS_OK) { 376 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3), 377 EC_ADDR(rap->rd_rtlddbpriv))); 378 return (RD_DBERR); 379 } 380 #if defined(_LP64) && !defined(_ELF64) 381 /*LINTED*/ 382 db_priv.rtd_objpad = (uint32_t)padsize; 383 #else 384 db_priv.rtd_objpad = padsize; 385 #endif 386 if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv, 387 sizeof (Rtld_db_priv)) != PS_OK) { 388 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2), 389 EC_ADDR(rap->rd_rtlddbpriv))); 390 return (RD_DBERR); 391 } 392 return (RD_OK); 393 } 394 395 396 397 398 static rd_err_e 399 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr, 400 rl_iter_f *cb, void *client_data, uint_t *abort_iter) 401 { 402 while (lmaddr) { 403 Rt_map rmap; 404 rd_loadobj_t lobj; 405 int i; 406 ulong_t off; 407 Ehdr ehdr; 408 Phdr phdr; 409 410 if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap, 411 sizeof (Rt_map)) != PS_OK) { 412 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 413 return (RD_DBERR); 414 } 415 416 /* 417 * As of 'VERSION5' we only report objects 418 * which have been fully relocated. While the maps 419 * might be in a consistent state - if a object hasn't 420 * been relocated - it's not really ready for the debuggers 421 * to examine. This is mostly due to the fact that we 422 * might still be mucking with the text-segment, if 423 * we are - we could conflict with any break-points 424 * the debuggers might have set. 425 */ 426 if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) { 427 if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) { 428 lmaddr = (psaddr_t)NEXT(&rmap); 429 continue; 430 } 431 } 432 433 lobj.rl_base = (psaddr_t)ADDR(&rmap); 434 lobj.rl_lmident = ident; 435 lobj.rl_flags = 0; 436 lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap); 437 438 /* 439 * refnameaddr is only valid from a core file 440 * which is VERSION3 or greater. 441 */ 442 if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) { 443 lobj.rl_nameaddr = (psaddr_t)NAME(&rmap); 444 lobj.rl_bend = 0; 445 lobj.rl_padstart = 0; 446 lobj.rl_padend = 0; 447 } else { 448 lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap); 449 lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap); 450 lobj.rl_padstart = PADSTART(&rmap); 451 lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap); 452 453 } 454 455 if (rtld_db_version >= RD_VERSION2) 456 if (FLAGS(&rmap) & FLG_RT_IMGALLOC) 457 lobj.rl_flags |= RD_FLG_MEM_OBJECT; 458 if (rtld_db_version >= RD_VERSION2) { 459 lobj.rl_dynamic = (psaddr_t)DYN(&rmap); 460 } 461 462 if (rtld_db_version >= RD_VERSION4) 463 lobj.rl_tlsmodid = TLSMODID(&rmap); 464 465 /* 466 * Look for beginning of data segment. 467 * 468 * NOTE: the data segment can only be found for full 469 * processes and not from core images. 470 */ 471 lobj.rl_data_base = 0; 472 if (rap->rd_flags & RDF_FL_COREFILE) 473 lobj.rl_data_base = 0; 474 else { 475 off = ADDR(&rmap); 476 if (ps_pread(rap->rd_psp, off, (char *)&ehdr, 477 sizeof (Ehdr)) != PS_OK) { 478 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 479 return (RD_DBERR); 480 } 481 off += sizeof (Ehdr); 482 for (i = 0; i < ehdr.e_phnum; i++) { 483 if (ps_pread(rap->rd_psp, off, (char *)&phdr, 484 sizeof (Phdr)) != PS_OK) { 485 LOG(ps_plog(MSG_ORIG( 486 MSG_DB_LKMAPFAIL))); 487 return (RD_DBERR); 488 } 489 if ((phdr.p_type == PT_LOAD) && 490 (phdr.p_flags & PF_W)) { 491 lobj.rl_data_base = phdr.p_vaddr; 492 if (ehdr.e_type == ET_DYN) 493 lobj.rl_data_base += 494 ADDR(&rmap); 495 break; 496 } 497 off += ehdr.e_phentsize; 498 } 499 } 500 501 502 /* 503 * When we transfer control to the client we free the 504 * lock and re-atain it after we've returned from the 505 * client. This is to avoid any deadlock situations. 506 */ 507 LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data, 508 EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident))); 509 RDAGUNLOCK(rap); 510 if ((*cb)(&lobj, client_data) == 0) { 511 LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0))); 512 RDAGLOCK(rap); 513 *abort_iter = 1; 514 break; 515 } 516 RDAGLOCK(rap); 517 lmaddr = (psaddr_t)NEXT(&rmap); 518 } 519 return (RD_OK); 520 } 521 522 523 rd_err_e 524 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 525 { 526 Rtld_db_priv db_priv; 527 TList list; 528 TListnode lnode; 529 Addr lnp; 530 unsigned long ident; 531 rd_err_e rc; 532 uint_t abort_iter = 0; 533 534 LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 535 client_data)); 536 537 if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 538 sizeof (Rtld_db_priv)) != PS_OK) { 539 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 540 EC_ADDR(rap->rd_rtlddbpriv))); 541 return (RD_DBERR); 542 } 543 544 if (db_priv.rtd_dynlmlst == 0) { 545 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 546 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 547 return (RD_NOMAPS); 548 } 549 550 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list, 551 sizeof (TList)) != PS_OK) { 552 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 553 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 554 return (RD_DBERR); 555 } 556 557 if (list.head == 0) { 558 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 559 EC_ADDR((uintptr_t)list.head))); 560 return (RD_NOMAPS); 561 } 562 563 564 if (cb == 0) { 565 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 566 return (RD_ERR); 567 } 568 569 for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) { 570 Lm_list lml; 571 572 /* 573 * Iterate through the List of Lm_list's. 574 */ 575 if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode, 576 sizeof (TListnode)) != PS_OK) { 577 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 578 EC_ADDR(lnp))); 579 return (RD_DBERR); 580 } 581 582 if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml, 583 sizeof (Lm_list)) != PS_OK) { 584 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 585 EC_ADDR((uintptr_t)lnode.data))); 586 return (RD_DBERR); 587 } 588 589 /* 590 * Determine IDENT of current LM_LIST 591 */ 592 if (lml.lm_flags & LML_FLG_BASELM) 593 ident = LM_ID_BASE; 594 else if (lml.lm_flags & LML_FLG_RTLDLM) 595 ident = LM_ID_LDSO; 596 else 597 ident = (unsigned long)lnode.data; 598 599 if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head, 600 cb, client_data, &abort_iter)) != RD_OK) { 601 return (rc); 602 } 603 if (abort_iter) 604 break; 605 } 606 return (rc); 607 } 608