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 #include <stdlib.h> 29 #include <stdio.h> 30 #include <proc_service.h> 31 #include <link.h> 32 #include <rtld_db.h> 33 #include <rtld.h> 34 #include <_rtld_db.h> 35 #include <msg.h> 36 #include <limits.h> 37 #include <string.h> 38 #include <sys/param.h> 39 40 /* 41 * 64-bit builds are going to compile this module twice, the 42 * second time with _ELF64 defined. These defines should make 43 * all the necessary adjustments to the code. 44 */ 45 #ifdef _LP64 46 #ifdef _ELF64 47 #define _rd_event_enable32 _rd_event_enable64 48 #define _rd_event_getmsg32 _rd_event_getmsg64 49 #define _rd_get_dyns32 _rd_get_dyns64 50 #define _rd_get_ehdr32 _rd_get_ehdr64 51 #define _rd_objpad_enable32 _rd_objpad_enable64 52 #define _rd_loadobj_iter32 _rd_loadobj_iter64 53 #define _rd_reset32 _rd_reset64 54 #define find_dynamic_ent32 find_dynamic_ent64 55 #define validate_rdebug32 validate_rdebug64 56 #define TList List 57 #define TListnode Listnode 58 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS64 59 #else /* ELF32 */ 60 #define Rt_map Rt_map32 61 #define Rtld_db_priv Rtld_db_priv32 62 #define TList List32 63 #define TListnode Listnode32 64 #define Lm_list Lm_list32 65 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS32 66 #endif /* _ELF64 */ 67 #else /* _LP64 */ 68 #define TList List 69 #define TListnode Listnode 70 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS32 71 #endif /* _LP64 */ 72 73 /* 74 * BrandZ added ps_pbrandname(). Many debuggers that link directly 75 * against librtld_db.so may not implement this interface. Hence 76 * we won't call the function directly, instead we'll try to look it 77 * up using the linker first and only invoke it if we find it. 78 */ 79 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *, 80 char *, size_t); 81 82 rd_err_e 83 validate_rdebug32(struct rd_agent *rap) 84 { 85 struct ps_prochandle *php = rap->rd_psp; 86 psaddr_t db_privp; 87 Rtld_db_priv db_priv; 88 89 if (rap->rd_rdebug == 0) 90 return (RD_ERR); 91 /* 92 * The rtld_db_priv structure contains both the traditional (exposed) 93 * r_debug structure as well as private data only available to 94 * this library. 95 */ 96 db_privp = rap->rd_rdebug; 97 98 /* 99 * Verify that librtld_db & rtld are at the proper revision 100 * levels. 101 */ 102 if (ps_pread(php, db_privp, (char *)&db_priv, 103 sizeof (Rtld_db_priv)) != PS_OK) { 104 LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1), 105 EC_ADDR(db_privp))); 106 return (RD_DBERR); 107 } 108 109 if ((db_priv.rtd_version < R_RTLDDB_VERSION1) || 110 (db_priv.rtd_version > R_RTLDDB_VERSION)) { 111 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 112 db_priv.rtd_version, R_RTLDDB_VERSION)); 113 return (RD_NOCAPAB); 114 } 115 116 /* 117 * Is the image being examined from a core file or not. 118 * If it is a core file then the following write will fail. 119 */ 120 if (ps_pwrite(php, db_privp, (char *)&db_priv, 121 sizeof (Rtld_db_priv)) != PS_OK) 122 rap->rd_flags |= RDF_FL_COREFILE; 123 124 /* 125 * If this *is not* a core file then rtld_db & ld.so.1 are 126 * considered tightly coupled. If the versions of our private 127 * data structures don't match - fail! 128 */ 129 if (((rap->rd_flags & RDF_FL_COREFILE) == 0) && 130 (db_priv.rtd_version != R_RTLDDB_VERSION)) { 131 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 132 db_priv.rtd_version, R_RTLDDB_VERSION)); 133 return (RD_NOCAPAB); 134 } 135 136 rap->rd_rdebugvers = db_priv.rtd_version; 137 rap->rd_rtlddbpriv = db_privp; 138 139 LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug), 140 R_RTLDDB_VERSION, rap->rd_rdebugvers, 141 rap->rd_flags & RDF_FL_COREFILE)); 142 return (RD_OK); 143 } 144 145 146 rd_err_e 147 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr, 148 Xword dyntag, Dyn *dyn) 149 { 150 struct ps_prochandle *php = rap->rd_psp; 151 Dyn d; 152 153 d.d_tag = DT_NULL; 154 do { 155 if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) != 156 PS_OK) { 157 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4), 158 EC_ADDR(dynaddr))); 159 return (RD_DBERR); 160 } 161 dynaddr += sizeof (d); 162 if (d.d_tag == dyntag) 163 break; 164 } while (d.d_tag != DT_NULL); 165 if (d.d_tag == dyntag) { 166 *dyn = d; 167 LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag), 168 EC_ADDR(d.d_un.d_val))); 169 return (RD_OK); 170 } 171 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag))); 172 return (RD_DBERR); 173 } 174 175 extern char rtld_db_helper_path[MAXPATHLEN]; 176 177 rd_err_e 178 _rd_reset32(struct rd_agent *rap) 179 { 180 psaddr_t symaddr; 181 struct ps_prochandle *php = rap->rd_psp; 182 const auxv_t *auxvp = NULL; 183 rd_err_e rc = RD_OK; 184 char brandname[MAXPATHLEN]; 185 char brandlib[MAXPATHLEN]; 186 ps_pbrandname_fp_t ps_pbrandname; 187 188 /* 189 * librtld_db attempts three different methods to find 190 * the r_debug structure which is required to 191 * initialize itself. The methods are: 192 * method1: 193 * entirely independent of any text segment 194 * and relies on the AT_SUN_LDDATA auxvector 195 * to find the ld.so.1::rdebug structure. 196 * method2: 197 * lookup symbols in ld.so.1's symbol table 198 * to find the r_debug symbol. 199 * method3: 200 * (old dbx method) dependent upon the 201 * text segment/symbol table of the 202 * executable and not ld.so.1. We lookup the 203 * _DYNAMIC symbol in the executable and look for 204 * the DT_DEBUG entry in the .dynamic table. This 205 * points to rdebug. 206 * 207 * If none of that works - we fail. 208 */ 209 LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel)); 210 /* 211 * Method1 212 * 213 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA 214 */ 215 216 if (ps_pauxv(php, &auxvp) != PS_OK) { 217 LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV))); 218 rc = RD_ERR; 219 } 220 221 rap->rd_rdebug = 0; 222 223 if (auxvp != NULL) { 224 rc = RD_ERR; 225 while (auxvp->a_type != AT_NULL) { 226 if (auxvp->a_type == AT_SUN_LDDATA) { 227 /* LINTED */ 228 rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr; 229 LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA), 230 rap->rd_rdebug)); 231 rc = validate_rdebug32(rap); 232 break; 233 } 234 auxvp++; 235 } 236 } 237 238 /* 239 * method2 - look for r_rdebug symbol in ld.so.1 240 */ 241 if (rc != RD_OK) { 242 /* 243 * If the AT_SUN_LDDATA auxv vector is not present 244 * fall back on doing a symlookup of 245 * the r_debug symbol. This is for backward 246 * compatiblity with older OS's 247 */ 248 LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA))); 249 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG), 250 &symaddr) != PS_OK) { 251 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 252 MSG_ORIG(MSG_SYM_DEBUG))); 253 rc = RD_DBERR; 254 } else { 255 rap->rd_rdebug = symaddr; 256 LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG), 257 EC_ADDR(symaddr))); 258 rc = validate_rdebug32(rap); 259 } 260 } 261 262 263 /* 264 * method3 - find DT_DEBUG in the executables .dynamic section. 265 */ 266 if (rc != RD_OK) { 267 Dyn dyn; 268 if (ps_pglobal_lookup(php, PS_OBJ_EXEC, 269 MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) { 270 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC))); 271 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 272 return (rc); 273 } 274 rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn); 275 if (rc != RD_OK) { 276 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 277 return (rc); 278 } 279 rap->rd_rdebug = dyn.d_un.d_ptr; 280 rc = validate_rdebug32(rap); 281 if (rc != RD_OK) { 282 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 283 return (rc); 284 } 285 } 286 287 /* 288 * If we are debugging a branded executable, load the appropriate 289 * helper library, and call its initialization routine. Being unable 290 * to load the helper library is not a critical error. (Hopefully 291 * we'll still be able to access some objects in the target.) 292 */ 293 ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname"); 294 while ((ps_pbrandname != NULL) && 295 (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) { 296 const char *isa = ""; 297 298 #ifdef _LP64 299 isa = MSG_ORIG(MSG_DB_64BIT_PREFIX); 300 #endif /* _LP64 */ 301 302 if (rtld_db_helper_path[0] != '\0') 303 (void) snprintf(brandlib, MAXPATHLEN, 304 MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX), 305 rtld_db_helper_path, 306 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 307 brandname); 308 else 309 (void) snprintf(brandlib, MAXPATHLEN, 310 MSG_ORIG(MSG_DB_BRAND_HELPERPATH), 311 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 312 brandname); 313 314 rap->rd_helper.rh_dlhandle = dlopen(brandlib, 315 RTLD_LAZY | RTLD_LOCAL); 316 if (rap->rd_helper.rh_dlhandle == NULL) { 317 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED), 318 brandlib)); 319 break; 320 } 321 322 rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle, 323 MSG_ORIG(MSG_SYM_BRANDOPS)); 324 if (rap->rd_helper.rh_ops == NULL) { 325 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS), 326 brandlib)); 327 (void) dlclose(rap->rd_helper.rh_dlhandle); 328 rap->rd_helper.rh_dlhandle = NULL; 329 break; 330 } 331 332 rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap, 333 php); 334 if (rap->rd_helper.rh_data == NULL) { 335 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED))); 336 (void) dlclose(rap->rd_helper.rh_dlhandle); 337 rap->rd_helper.rh_dlhandle = NULL; 338 rap->rd_helper.rh_ops = NULL; 339 break; 340 } 341 342 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname)); 343 break; 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_iter) 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_iter = 1; 674 break; 675 } 676 RDAGLOCK(rap); 677 lmaddr = (psaddr_t)NEXT(&rmap); 678 } 679 return (RD_OK); 680 } 681 682 683 rd_err_e 684 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 685 { 686 Rtld_db_priv db_priv; 687 TList list; 688 TListnode lnode; 689 Addr lnp; 690 unsigned long ident; 691 rd_err_e rc; 692 uint_t abort_iter = 0; 693 694 LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 695 client_data)); 696 697 if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 698 sizeof (Rtld_db_priv)) != PS_OK) { 699 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 700 EC_ADDR(rap->rd_rtlddbpriv))); 701 return (RD_DBERR); 702 } 703 704 if (db_priv.rtd_dynlmlst == 0) { 705 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 706 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 707 return (RD_NOMAPS); 708 } 709 710 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list, 711 sizeof (TList)) != PS_OK) { 712 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 713 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 714 return (RD_DBERR); 715 } 716 717 if (list.head == 0) { 718 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 719 EC_ADDR((uintptr_t)list.head))); 720 return (RD_NOMAPS); 721 } 722 723 724 if (cb == 0) { 725 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 726 return (RD_ERR); 727 } 728 729 for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) { 730 Lm_list lml; 731 732 /* 733 * Iterate through the List of Lm_list's. 734 */ 735 if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode, 736 sizeof (TListnode)) != PS_OK) { 737 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 738 EC_ADDR(lnp))); 739 return (RD_DBERR); 740 } 741 742 if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml, 743 sizeof (Lm_list)) != PS_OK) { 744 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 745 EC_ADDR((uintptr_t)lnode.data))); 746 return (RD_DBERR); 747 } 748 749 /* 750 * Determine IDENT of current LM_LIST 751 */ 752 if (lml.lm_flags & LML_FLG_BASELM) 753 ident = LM_ID_BASE; 754 else if (lml.lm_flags & LML_FLG_RTLDLM) 755 ident = LM_ID_LDSO; 756 else 757 ident = (unsigned long)lnode.data; 758 759 if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head, 760 cb, client_data, &abort_iter)) != RD_OK) { 761 return (rc); 762 } 763 if (abort_iter) 764 break; 765 } 766 767 if (rc != RD_OK) 768 return (rc); 769 770 if (rap->rd_helper.rh_ops != NULL) 771 return (rap->rd_helper.rh_ops->rho_loadobj_iter( 772 rap->rd_helper.rh_data, cb, client_data)); 773 774 return (RD_OK); 775 } 776