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 *dynpp_sz = phdr.p_filesz; 452 return (RD_OK); 453 } 454 455 rd_err_e 456 _rd_event_enable32(rd_agent_t *rap, int onoff) 457 { 458 struct ps_prochandle *php = rap->rd_psp; 459 Rtld_db_priv rdb; 460 461 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff)); 462 /* 463 * Tell the debugged process that debugging is occuring 464 * This will enable the storing of event messages so that 465 * the can be gathered by the debugger. 466 */ 467 if (ps_pread(php, rap->rd_rdebug, (char *)&rdb, 468 sizeof (Rtld_db_priv)) != PS_OK) { 469 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1), 470 EC_ADDR((uintptr_t)&rdb))); 471 return (RD_DBERR); 472 } 473 474 if (onoff) 475 rdb.rtd_rdebug.r_flags |= RD_FL_DBG; 476 else 477 rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG; 478 479 if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb, 480 sizeof (Rtld_db_priv)) != PS_OK) { 481 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1), 482 EC_ADDR((uintptr_t)&rdb))); 483 return (RD_DBERR); 484 } 485 486 return (RD_OK); 487 } 488 489 490 rd_err_e 491 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg) 492 { 493 Rtld_db_priv rdb; 494 495 if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb, 496 sizeof (Rtld_db_priv)) != PS_OK) { 497 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2), 498 EC_ADDR(rap->rd_rdebug))); 499 return (RD_DBERR); 500 } 501 emsg->type = rdb.rtd_rdebug.r_rdevent; 502 if (emsg->type == RD_DLACTIVITY) { 503 switch (rdb.rtd_rdebug.r_state) { 504 case RT_CONSISTENT: 505 emsg->u.state = RD_CONSISTENT; 506 break; 507 case RT_ADD: 508 emsg->u.state = RD_ADD; 509 break; 510 case RT_DELETE: 511 emsg->u.state = RD_DELETE; 512 break; 513 } 514 } else 515 emsg->u.state = RD_NOSTATE; 516 517 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel, 518 emsg->type, emsg->u.state)); 519 520 return (RD_OK); 521 } 522 523 524 rd_err_e 525 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize) 526 { 527 Rtld_db_priv db_priv; 528 struct ps_prochandle *php = rap->rd_psp; 529 530 LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize))); 531 532 if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv, 533 sizeof (Rtld_db_priv)) != PS_OK) { 534 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3), 535 EC_ADDR(rap->rd_rtlddbpriv))); 536 return (RD_DBERR); 537 } 538 #if defined(_LP64) && !defined(_ELF64) 539 /*LINTED*/ 540 db_priv.rtd_objpad = (uint32_t)padsize; 541 #else 542 db_priv.rtd_objpad = padsize; 543 #endif 544 if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv, 545 sizeof (Rtld_db_priv)) != PS_OK) { 546 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2), 547 EC_ADDR(rap->rd_rtlddbpriv))); 548 return (RD_DBERR); 549 } 550 return (RD_OK); 551 } 552 553 static rd_err_e 554 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr, 555 rl_iter_f *cb, void *client_data, uint_t *abort_iter) 556 { 557 while (lmaddr) { 558 Rt_map rmap; 559 rd_loadobj_t lobj; 560 int i; 561 ulong_t off; 562 Ehdr ehdr; 563 Phdr phdr; 564 565 if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap, 566 sizeof (Rt_map)) != PS_OK) { 567 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 568 return (RD_DBERR); 569 } 570 571 /* 572 * As of 'VERSION5' we only report objects 573 * which have been fully relocated. While the maps 574 * might be in a consistent state - if a object hasn't 575 * been relocated - it's not really ready for the debuggers 576 * to examine. This is mostly due to the fact that we 577 * might still be mucking with the text-segment, if 578 * we are - we could conflict with any break-points 579 * the debuggers might have set. 580 */ 581 if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) { 582 if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) { 583 lmaddr = (psaddr_t)NEXT(&rmap); 584 continue; 585 } 586 } 587 588 lobj.rl_base = (psaddr_t)ADDR(&rmap); 589 lobj.rl_flags = 0; 590 lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap); 591 if ((rap->rd_helper.rh_ops != NULL) && 592 (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE)) 593 lobj.rl_lmident = 594 rap->rd_helper.rh_ops->rho_lmid; 595 else 596 lobj.rl_lmident = ident; 597 598 /* 599 * refnameaddr is only valid from a core file 600 * which is VERSION3 or greater. 601 */ 602 if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) { 603 lobj.rl_nameaddr = (psaddr_t)NAME(&rmap); 604 lobj.rl_bend = 0; 605 lobj.rl_padstart = 0; 606 lobj.rl_padend = 0; 607 } else { 608 lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap); 609 lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap); 610 lobj.rl_padstart = PADSTART(&rmap); 611 lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap); 612 613 } 614 615 if (rtld_db_version >= RD_VERSION2) 616 if (FLAGS(&rmap) & FLG_RT_IMGALLOC) 617 lobj.rl_flags |= RD_FLG_MEM_OBJECT; 618 if (rtld_db_version >= RD_VERSION2) { 619 lobj.rl_dynamic = (psaddr_t)DYN(&rmap); 620 } 621 622 if (rtld_db_version >= RD_VERSION4) 623 lobj.rl_tlsmodid = TLSMODID(&rmap); 624 625 /* 626 * Look for beginning of data segment. 627 * 628 * NOTE: the data segment can only be found for full 629 * processes and not from core images. 630 */ 631 lobj.rl_data_base = 0; 632 if (rap->rd_flags & RDF_FL_COREFILE) 633 lobj.rl_data_base = 0; 634 else { 635 off = ADDR(&rmap); 636 if (ps_pread(rap->rd_psp, off, (char *)&ehdr, 637 sizeof (Ehdr)) != PS_OK) { 638 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 639 return (RD_DBERR); 640 } 641 off += sizeof (Ehdr); 642 for (i = 0; i < ehdr.e_phnum; i++) { 643 if (ps_pread(rap->rd_psp, off, (char *)&phdr, 644 sizeof (Phdr)) != PS_OK) { 645 LOG(ps_plog(MSG_ORIG( 646 MSG_DB_LKMAPFAIL))); 647 return (RD_DBERR); 648 } 649 if ((phdr.p_type == PT_LOAD) && 650 (phdr.p_flags & PF_W)) { 651 lobj.rl_data_base = phdr.p_vaddr; 652 if (ehdr.e_type == ET_DYN) 653 lobj.rl_data_base += 654 ADDR(&rmap); 655 break; 656 } 657 off += ehdr.e_phentsize; 658 } 659 } 660 661 /* 662 * When we transfer control to the client we free the 663 * lock and re-atain it after we've returned from the 664 * client. This is to avoid any deadlock situations. 665 */ 666 LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data, 667 EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident))); 668 RDAGUNLOCK(rap); 669 if ((*cb)(&lobj, client_data) == 0) { 670 LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0))); 671 RDAGLOCK(rap); 672 *abort_iter = 1; 673 break; 674 } 675 RDAGLOCK(rap); 676 lmaddr = (psaddr_t)NEXT(&rmap); 677 } 678 return (RD_OK); 679 } 680 681 682 rd_err_e 683 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 684 { 685 Rtld_db_priv db_priv; 686 TList list; 687 TListnode lnode; 688 Addr lnp; 689 unsigned long ident; 690 rd_err_e rc; 691 uint_t abort_iter = 0; 692 693 LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 694 client_data)); 695 696 if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 697 sizeof (Rtld_db_priv)) != PS_OK) { 698 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 699 EC_ADDR(rap->rd_rtlddbpriv))); 700 return (RD_DBERR); 701 } 702 703 if (db_priv.rtd_dynlmlst == 0) { 704 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 705 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 706 return (RD_NOMAPS); 707 } 708 709 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list, 710 sizeof (TList)) != PS_OK) { 711 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 712 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 713 return (RD_DBERR); 714 } 715 716 if (list.head == 0) { 717 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 718 EC_ADDR((uintptr_t)list.head))); 719 return (RD_NOMAPS); 720 } 721 722 723 if (cb == 0) { 724 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 725 return (RD_ERR); 726 } 727 728 for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) { 729 Lm_list lml; 730 731 /* 732 * Iterate through the List of Lm_list's. 733 */ 734 if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode, 735 sizeof (TListnode)) != PS_OK) { 736 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 737 EC_ADDR(lnp))); 738 return (RD_DBERR); 739 } 740 741 if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml, 742 sizeof (Lm_list)) != PS_OK) { 743 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 744 EC_ADDR((uintptr_t)lnode.data))); 745 return (RD_DBERR); 746 } 747 748 /* 749 * Determine IDENT of current LM_LIST 750 */ 751 if (lml.lm_flags & LML_FLG_BASELM) 752 ident = LM_ID_BASE; 753 else if (lml.lm_flags & LML_FLG_RTLDLM) 754 ident = LM_ID_LDSO; 755 else 756 ident = (unsigned long)lnode.data; 757 758 if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head, 759 cb, client_data, &abort_iter)) != RD_OK) { 760 return (rc); 761 } 762 if (abort_iter) 763 break; 764 } 765 766 if (rc != RD_OK) 767 return (rc); 768 769 if (rap->rd_helper.rh_ops != NULL) 770 return (rap->rd_helper.rh_ops->rho_loadobj_iter( 771 rap->rd_helper.rh_data, cb, client_data)); 772 773 return (RD_OK); 774 } 775