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