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