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