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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <proc_service.h> 29 #include <link.h> 30 #include <rtld_db.h> 31 #include <rtld.h> 32 #include <alist.h> 33 #include <_rtld_db.h> 34 #include <msg.h> 35 #include <limits.h> 36 #include <string.h> 37 #include <sys/param.h> 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_event_enable32 _rd_event_enable64 47 #define _rd_event_getmsg32 _rd_event_getmsg64 48 #define _rd_get_dyns32 _rd_get_dyns64 49 #define _rd_get_ehdr32 _rd_get_ehdr64 50 #define _rd_objpad_enable32 _rd_objpad_enable64 51 #define _rd_loadobj_iter32 _rd_loadobj_iter64 52 #define _rd_reset32 _rd_reset64 53 #define find_dynamic_ent32 find_dynamic_ent64 54 #define validate_rdebug32 validate_rdebug64 55 #define TAPlist APlist 56 #define TLm_list Lm_list 57 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_64 58 #else /* ELF32 */ 59 #define Rt_map Rt_map32 60 #define Rtld_db_priv Rtld_db_priv32 61 #define TAPlist APlist32 62 #define TLm_list Lm_list32 63 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32 64 #endif /* _ELF64 */ 65 #else /* _LP64 */ 66 #define TAPlist APlist 67 #define TLm_list Lm_list 68 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32 69 #endif /* _LP64 */ 70 71 /* 72 * BrandZ added ps_pbrandname(). Many debuggers that link directly 73 * against librtld_db.so may not implement this interface. Hence 74 * we won't call the function directly, instead we'll try to look it 75 * up using the linker first and only invoke it if we find it. 76 */ 77 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *, 78 char *, size_t); 79 80 rd_err_e 81 validate_rdebug32(struct rd_agent *rap) 82 { 83 struct ps_prochandle *php = rap->rd_psp; 84 psaddr_t db_privp; 85 Rtld_db_priv db_priv; 86 87 if (rap->rd_rdebug == 0) 88 return (RD_ERR); 89 /* 90 * The rtld_db_priv structure contains both the traditional (exposed) 91 * r_debug structure as well as private data only available to 92 * this library. 93 */ 94 db_privp = rap->rd_rdebug; 95 96 /* 97 * Verify that librtld_db & rtld are at the proper revision 98 * levels. 99 */ 100 if (ps_pread(php, db_privp, (char *)&db_priv, 101 sizeof (Rtld_db_priv)) != PS_OK) { 102 LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1), 103 EC_ADDR(db_privp))); 104 return (RD_DBERR); 105 } 106 107 if ((db_priv.rtd_version < R_RTLDDB_VERSION1) || 108 (db_priv.rtd_version > R_RTLDDB_VERSION)) { 109 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 110 db_priv.rtd_version, R_RTLDDB_VERSION)); 111 return (RD_NOCAPAB); 112 } 113 114 /* 115 * Is the image being examined from a core file or not. 116 * If it is a core file then the following write will fail. 117 */ 118 if (ps_pwrite(php, db_privp, (char *)&db_priv, 119 sizeof (Rtld_db_priv)) != PS_OK) 120 rap->rd_flags |= RDF_FL_COREFILE; 121 122 /* 123 * If this *is not* a core file then rtld_db & ld.so.1 are 124 * considered tightly coupled. If the versions of our private 125 * data structures don't match - fail! 126 */ 127 if (((rap->rd_flags & RDF_FL_COREFILE) == 0) && 128 (db_priv.rtd_version != R_RTLDDB_VERSION)) { 129 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 130 db_priv.rtd_version, R_RTLDDB_VERSION)); 131 return (RD_NOCAPAB); 132 } 133 134 rap->rd_rdebugvers = db_priv.rtd_version; 135 rap->rd_rtlddbpriv = db_privp; 136 137 LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug), 138 R_RTLDDB_VERSION, rap->rd_rdebugvers, 139 rap->rd_flags & RDF_FL_COREFILE)); 140 return (RD_OK); 141 } 142 143 144 rd_err_e 145 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr, 146 Xword dyntag, Dyn *dyn) 147 { 148 struct ps_prochandle *php = rap->rd_psp; 149 Dyn d; 150 151 d.d_tag = DT_NULL; 152 do { 153 if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) != 154 PS_OK) { 155 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4), 156 EC_ADDR(dynaddr))); 157 return (RD_DBERR); 158 } 159 dynaddr += sizeof (d); 160 if (d.d_tag == dyntag) 161 break; 162 } while (d.d_tag != DT_NULL); 163 if (d.d_tag == dyntag) { 164 *dyn = d; 165 LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag), 166 EC_ADDR(d.d_un.d_val))); 167 return (RD_OK); 168 } 169 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag))); 170 return (RD_DBERR); 171 } 172 173 extern char rtld_db_helper_path[MAXPATHLEN]; 174 175 rd_err_e 176 _rd_reset32(struct rd_agent *rap) 177 { 178 psaddr_t symaddr; 179 struct ps_prochandle *php = rap->rd_psp; 180 const auxv_t *auxvp = NULL; 181 rd_err_e rc = RD_OK; 182 char brandname[MAXPATHLEN]; 183 char brandlib[MAXPATHLEN]; 184 ps_pbrandname_fp_t ps_pbrandname; 185 186 /* 187 * librtld_db attempts three different methods to find 188 * the r_debug structure which is required to 189 * initialize itself. The methods are: 190 * method1: 191 * entirely independent of any text segment 192 * and relies on the AT_SUN_LDDATA auxvector 193 * to find the ld.so.1::rdebug structure. 194 * method2: 195 * lookup symbols in ld.so.1's symbol table 196 * to find the r_debug symbol. 197 * method3: 198 * (old dbx method) dependent upon the 199 * text segment/symbol table of the 200 * executable and not ld.so.1. We lookup the 201 * _DYNAMIC symbol in the executable and look for 202 * the DT_DEBUG entry in the .dynamic table. This 203 * points to rdebug. 204 * 205 * If none of that works - we fail. 206 */ 207 LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel)); 208 /* 209 * Method1 210 * 211 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA 212 */ 213 214 if (ps_pauxv(php, &auxvp) != PS_OK) { 215 LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV))); 216 rc = RD_ERR; 217 } 218 219 rap->rd_rdebug = 0; 220 221 if (auxvp != NULL) { 222 rc = RD_ERR; 223 while (auxvp->a_type != AT_NULL) { 224 if (auxvp->a_type == AT_SUN_LDDATA) { 225 /* LINTED */ 226 rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr; 227 LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA), 228 rap->rd_rdebug)); 229 rc = validate_rdebug32(rap); 230 break; 231 } 232 auxvp++; 233 } 234 } 235 236 /* 237 * method2 - look for r_rdebug symbol in ld.so.1 238 */ 239 if (rc != RD_OK) { 240 /* 241 * If the AT_SUN_LDDATA auxv vector is not present 242 * fall back on doing a symlookup of 243 * the r_debug symbol. This is for backward 244 * compatiblity with older OS's 245 */ 246 LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA))); 247 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG), 248 &symaddr) != PS_OK) { 249 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 250 MSG_ORIG(MSG_SYM_DEBUG))); 251 rc = RD_DBERR; 252 } else { 253 rap->rd_rdebug = symaddr; 254 LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG), 255 EC_ADDR(symaddr))); 256 rc = validate_rdebug32(rap); 257 } 258 } 259 260 261 /* 262 * method3 - find DT_DEBUG in the executables .dynamic section. 263 */ 264 if (rc != RD_OK) { 265 Dyn dyn; 266 if (ps_pglobal_lookup(php, PS_OBJ_EXEC, 267 MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) { 268 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC))); 269 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 270 return (rc); 271 } 272 rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn); 273 if (rc != RD_OK) { 274 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 275 return (rc); 276 } 277 rap->rd_rdebug = dyn.d_un.d_ptr; 278 rc = validate_rdebug32(rap); 279 if (rc != RD_OK) { 280 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 281 return (rc); 282 } 283 } 284 285 /* 286 * If we are debugging a branded executable, load the appropriate 287 * helper library, and call its initialization routine. Being unable 288 * to load the helper library is not a critical error. (Hopefully 289 * we'll still be able to access some objects in the target.) 290 */ 291 ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname"); 292 while ((ps_pbrandname != NULL) && 293 (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) { 294 const char *isa = ""; 295 296 #ifdef _LP64 297 isa = MSG_ORIG(MSG_DB_64BIT_PREFIX); 298 #endif /* _LP64 */ 299 300 if (rtld_db_helper_path[0] != '\0') 301 (void) snprintf(brandlib, MAXPATHLEN, 302 MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX), 303 rtld_db_helper_path, 304 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 305 brandname); 306 else 307 (void) snprintf(brandlib, MAXPATHLEN, 308 MSG_ORIG(MSG_DB_BRAND_HELPERPATH), 309 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 310 brandname); 311 312 rap->rd_helper.rh_dlhandle = dlopen(brandlib, 313 RTLD_LAZY | RTLD_LOCAL); 314 if (rap->rd_helper.rh_dlhandle == NULL) { 315 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED), 316 brandlib)); 317 break; 318 } 319 320 rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle, 321 MSG_ORIG(MSG_SYM_BRANDOPS)); 322 if (rap->rd_helper.rh_ops == NULL) { 323 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS), 324 brandlib)); 325 (void) dlclose(rap->rd_helper.rh_dlhandle); 326 rap->rd_helper.rh_dlhandle = NULL; 327 break; 328 } 329 330 rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap, 331 php); 332 if (rap->rd_helper.rh_data == NULL) { 333 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED))); 334 (void) dlclose(rap->rd_helper.rh_dlhandle); 335 rap->rd_helper.rh_dlhandle = NULL; 336 rap->rd_helper.rh_ops = NULL; 337 break; 338 } 339 340 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname)); 341 break; 342 343 /* NOTREACHED */ 344 } 345 346 if ((rap->rd_flags & RDF_FL_COREFILE) == 0) { 347 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 348 MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) { 349 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 350 MSG_ORIG(MSG_SYM_PREINIT))); 351 return (RD_DBERR); 352 } 353 rap->rd_preinit = symaddr; 354 355 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 356 MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) { 357 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 358 MSG_ORIG(MSG_SYM_POSTINIT))); 359 return (RD_DBERR); 360 } 361 rap->rd_postinit = symaddr; 362 363 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 364 MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) { 365 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 366 MSG_ORIG(MSG_SYM_DLACT))); 367 return (RD_DBERR); 368 } 369 rap->rd_dlact = symaddr; 370 rap->rd_tbinder = 0; 371 } 372 373 return (RD_OK); 374 } 375 376 rd_err_e 377 _rd_get_ehdr32(struct rd_agent *rap, 378 psaddr_t addr, Ehdr *ehdr, uint_t *phnum) 379 { 380 struct ps_prochandle *php = rap->rd_psp; 381 Shdr shdr; 382 383 if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) { 384 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 385 return (RD_ERR); 386 } 387 if (phnum == NULL) 388 return (RD_OK); 389 390 if (ehdr->e_phnum != PN_XNUM) { 391 *phnum = ehdr->e_phnum; 392 return (RD_OK); 393 } 394 395 /* deal with elf extended program headers */ 396 if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr))) 397 return (RD_ERR); 398 399 addr += ehdr->e_shoff; 400 if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) { 401 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 402 return (RD_ERR); 403 } 404 405 if (shdr.sh_info == 0) 406 return (RD_ERR); 407 408 *phnum = shdr.sh_info; 409 return (RD_OK); 410 } 411 412 rd_err_e 413 _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz) 414 { 415 struct ps_prochandle *php = rap->rd_psp; 416 rd_err_e err; 417 uint_t phnum; 418 Ehdr ehdr; 419 Phdr phdr; 420 Dyn *dynp; 421 int i; 422 423 /* We only need to muck with dyn elements for ET_DYN objects */ 424 if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK) 425 return (err); 426 427 for (i = 0; i < phnum; i++) { 428 psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize); 429 if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) { 430 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a))); 431 return (RD_ERR); 432 } 433 if (phdr.p_type == PT_DYNAMIC) 434 break; 435 } 436 if (i == phnum) 437 return (RD_ERR); 438 439 if ((dynp = malloc(phdr.p_filesz)) == NULL) 440 return (RD_ERR); 441 if (ehdr.e_type == ET_DYN) 442 phdr.p_vaddr += addr; 443 if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) { 444 free(dynp); 445 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), 446 EC_ADDR(phdr.p_vaddr))); 447 return (RD_ERR); 448 } 449 450 *dynpp = dynp; 451 if (dynpp_sz != NULL) 452 *dynpp_sz = phdr.p_filesz; 453 return (RD_OK); 454 } 455 456 rd_err_e 457 _rd_event_enable32(rd_agent_t *rap, int onoff) 458 { 459 struct ps_prochandle *php = rap->rd_psp; 460 Rtld_db_priv rdb; 461 462 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff)); 463 /* 464 * Tell the debugged process that debugging is occuring 465 * This will enable the storing of event messages so that 466 * the can be gathered by the debugger. 467 */ 468 if (ps_pread(php, rap->rd_rdebug, (char *)&rdb, 469 sizeof (Rtld_db_priv)) != PS_OK) { 470 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1), 471 EC_ADDR((uintptr_t)&rdb))); 472 return (RD_DBERR); 473 } 474 475 if (onoff) 476 rdb.rtd_rdebug.r_flags |= RD_FL_DBG; 477 else 478 rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG; 479 480 if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb, 481 sizeof (Rtld_db_priv)) != PS_OK) { 482 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1), 483 EC_ADDR((uintptr_t)&rdb))); 484 return (RD_DBERR); 485 } 486 487 return (RD_OK); 488 } 489 490 491 rd_err_e 492 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg) 493 { 494 Rtld_db_priv rdb; 495 496 if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb, 497 sizeof (Rtld_db_priv)) != PS_OK) { 498 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2), 499 EC_ADDR(rap->rd_rdebug))); 500 return (RD_DBERR); 501 } 502 emsg->type = rdb.rtd_rdebug.r_rdevent; 503 if (emsg->type == RD_DLACTIVITY) { 504 switch (rdb.rtd_rdebug.r_state) { 505 case RT_CONSISTENT: 506 emsg->u.state = RD_CONSISTENT; 507 break; 508 case RT_ADD: 509 emsg->u.state = RD_ADD; 510 break; 511 case RT_DELETE: 512 emsg->u.state = RD_DELETE; 513 break; 514 } 515 } else 516 emsg->u.state = RD_NOSTATE; 517 518 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel, 519 emsg->type, emsg->u.state)); 520 521 return (RD_OK); 522 } 523 524 525 rd_err_e 526 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize) 527 { 528 Rtld_db_priv db_priv; 529 struct ps_prochandle *php = rap->rd_psp; 530 531 LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize))); 532 533 if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv, 534 sizeof (Rtld_db_priv)) != PS_OK) { 535 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3), 536 EC_ADDR(rap->rd_rtlddbpriv))); 537 return (RD_DBERR); 538 } 539 #if defined(_LP64) && !defined(_ELF64) 540 /*LINTED*/ 541 db_priv.rtd_objpad = (uint32_t)padsize; 542 #else 543 db_priv.rtd_objpad = padsize; 544 #endif 545 if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv, 546 sizeof (Rtld_db_priv)) != PS_OK) { 547 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2), 548 EC_ADDR(rap->rd_rtlddbpriv))); 549 return (RD_DBERR); 550 } 551 return (RD_OK); 552 } 553 554 static rd_err_e 555 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr, 556 rl_iter_f *cb, void *client_data, uint_t *abort_iterp) 557 { 558 while (lmaddr) { 559 Rt_map rmap; 560 rd_loadobj_t lobj; 561 int i; 562 ulong_t off; 563 Ehdr ehdr; 564 Phdr phdr; 565 566 if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap, 567 sizeof (Rt_map)) != PS_OK) { 568 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 569 return (RD_DBERR); 570 } 571 572 /* 573 * As of 'VERSION5' we only report objects 574 * which have been fully relocated. While the maps 575 * might be in a consistent state - if a object hasn't 576 * been relocated - it's not really ready for the debuggers 577 * to examine. This is mostly due to the fact that we 578 * might still be mucking with the text-segment, if 579 * we are - we could conflict with any break-points 580 * the debuggers might have set. 581 */ 582 if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) { 583 if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) { 584 lmaddr = (psaddr_t)NEXT(&rmap); 585 continue; 586 } 587 } 588 589 lobj.rl_base = (psaddr_t)ADDR(&rmap); 590 lobj.rl_flags = 0; 591 lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap); 592 if ((rap->rd_helper.rh_ops != NULL) && 593 (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE)) 594 lobj.rl_lmident = 595 rap->rd_helper.rh_ops->rho_lmid; 596 else 597 lobj.rl_lmident = ident; 598 599 /* 600 * refnameaddr is only valid from a core file 601 * which is VERSION3 or greater. 602 */ 603 if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) { 604 lobj.rl_nameaddr = (psaddr_t)NAME(&rmap); 605 lobj.rl_bend = 0; 606 lobj.rl_padstart = 0; 607 lobj.rl_padend = 0; 608 } else { 609 lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap); 610 lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap); 611 lobj.rl_padstart = PADSTART(&rmap); 612 lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap); 613 614 } 615 616 if (rtld_db_version >= RD_VERSION2) 617 if (FLAGS(&rmap) & FLG_RT_IMGALLOC) 618 lobj.rl_flags |= RD_FLG_MEM_OBJECT; 619 if (rtld_db_version >= RD_VERSION2) { 620 lobj.rl_dynamic = (psaddr_t)DYN(&rmap); 621 } 622 623 if (rtld_db_version >= RD_VERSION4) 624 lobj.rl_tlsmodid = TLSMODID(&rmap); 625 626 /* 627 * Look for beginning of data segment. 628 * 629 * NOTE: the data segment can only be found for full 630 * processes and not from core images. 631 */ 632 lobj.rl_data_base = 0; 633 if (rap->rd_flags & RDF_FL_COREFILE) 634 lobj.rl_data_base = 0; 635 else { 636 off = ADDR(&rmap); 637 if (ps_pread(rap->rd_psp, off, (char *)&ehdr, 638 sizeof (Ehdr)) != PS_OK) { 639 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 640 return (RD_DBERR); 641 } 642 off += sizeof (Ehdr); 643 for (i = 0; i < ehdr.e_phnum; i++) { 644 if (ps_pread(rap->rd_psp, off, (char *)&phdr, 645 sizeof (Phdr)) != PS_OK) { 646 LOG(ps_plog(MSG_ORIG( 647 MSG_DB_LKMAPFAIL))); 648 return (RD_DBERR); 649 } 650 if ((phdr.p_type == PT_LOAD) && 651 (phdr.p_flags & PF_W)) { 652 lobj.rl_data_base = phdr.p_vaddr; 653 if (ehdr.e_type == ET_DYN) 654 lobj.rl_data_base += 655 ADDR(&rmap); 656 break; 657 } 658 off += ehdr.e_phentsize; 659 } 660 } 661 662 /* 663 * When we transfer control to the client we free the 664 * lock and re-atain it after we've returned from the 665 * client. This is to avoid any deadlock situations. 666 */ 667 LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data, 668 EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident))); 669 RDAGUNLOCK(rap); 670 if ((*cb)(&lobj, client_data) == 0) { 671 LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0))); 672 RDAGLOCK(rap); 673 *abort_iterp = 1; 674 break; 675 } 676 RDAGLOCK(rap); 677 lmaddr = (psaddr_t)NEXT(&rmap); 678 } 679 return (RD_OK); 680 } 681 682 683 static rd_err_e 684 _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data, 685 uint_t *abort_iterp) 686 { 687 Rtld_db_priv db_priv; 688 TAPlist apl; 689 uintptr_t datap, nitems; 690 Addr addr; 691 rd_err_e rc; 692 693 LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 694 client_data)); 695 696 if (cb == NULL) { 697 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 698 return (RD_ERR); 699 } 700 701 if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 702 sizeof (Rtld_db_priv)) != PS_OK) { 703 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 704 EC_ADDR(rap->rd_rtlddbpriv))); 705 return (RD_DBERR); 706 } 707 708 if (db_priv.rtd_dynlmlst == NULL) { 709 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 710 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 711 return (RD_NOMAPS); 712 } 713 714 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr, 715 sizeof (Addr)) != PS_OK) { 716 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 717 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 718 return (RD_DBERR); 719 } 720 721 if (addr == NULL) { 722 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 723 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 724 return (RD_NOMAPS); 725 } 726 727 if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl, 728 sizeof (TAPlist)) != PS_OK) { 729 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 730 EC_ADDR((uintptr_t)addr))); 731 return (RD_DBERR); 732 } 733 734 /* 735 * Iterate through each apl.ap_data[] entry. 736 */ 737 for (datap = (uintptr_t)((char *)(uintptr_t)addr + 738 ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0; 739 nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) { 740 TLm_list lm; 741 ulong_t ident; 742 743 /* 744 * Obtain the Lm_list address for this apl.ap_data[] entry. 745 */ 746 if (ps_pread(rap->rd_psp, (psaddr_t)datap, (char *)&addr, 747 sizeof (Addr)) != PS_OK) { 748 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 749 EC_ADDR(datap))); 750 return (RD_DBERR); 751 } 752 753 /* 754 * Obtain the Lm_list data for this Lm_list address. 755 */ 756 if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm, 757 sizeof (TLm_list)) != PS_OK) { 758 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6), 759 EC_ADDR((uintptr_t)addr))); 760 return (RD_DBERR); 761 } 762 763 /* 764 * Determine IDENT of current LM_LIST 765 */ 766 if (lm.lm_flags & LML_FLG_BASELM) 767 ident = LM_ID_BASE; 768 else if (lm.lm_flags & LML_FLG_RTLDLM) 769 ident = LM_ID_LDSO; 770 else 771 ident = (ulong_t)addr; 772 773 if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head, 774 cb, client_data, abort_iterp)) != RD_OK) { 775 return (rc); 776 } 777 if (*abort_iterp != 0) 778 break; 779 } 780 781 return (rc); 782 } 783 784 rd_err_e 785 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 786 { 787 rd_err_e rc, rc_brand = RD_OK; 788 uint_t abort_iter = 0; 789 790 /* First iterate over the native target objects */ 791 rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter); 792 if (abort_iter != 0) 793 return (rc); 794 795 /* Then iterate over any branded objects. */ 796 if ((rap->rd_helper.rh_ops != NULL) && 797 (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL)) 798 rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter( 799 rap->rd_helper.rh_data, cb, client_data); 800 801 rc = (rc != RD_OK) ? rc : rc_brand; 802 return (rc); 803 } 804