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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
  28  */
  29 
  30 #include        <stdlib.h>
  31 #include        <stdio.h>
  32 #include        <proc_service.h>
  33 #include        <link.h>
  34 #include        <rtld_db.h>
  35 #include        <rtld.h>
  36 #include        <alist.h>
  37 #include        <list.h>
  38 #include        <_rtld_db.h>
  39 #include        <msg.h>
  40 #include        <limits.h>
  41 #include        <string.h>
  42 #include        <sys/param.h>
  43 
  44 /*
  45  * We want to include zone.h to pull in the prototype for zone_get_nroot(),
  46  * but we need to avoid pulling in <sys/stream.h>, which has a definition
  47  * of M_DATA that conflicts with the ELF-related definition in machdep_*.h.
  48  */
  49 #define         _SYS_STREAM_H
  50 #include        <zone.h>
  51 
  52 /*
  53  * 64-bit builds are going to compile this module twice, the
  54  * second time with _ELF64 defined.  These defines should make
  55  * all the necessary adjustments to the code.
  56  */
  57 #ifdef _LP64
  58 #ifdef _ELF64
  59 #define _rd_event_enable32      _rd_event_enable64
  60 #define _rd_event_getmsg32      _rd_event_getmsg64
  61 #define _rd_get_dyns32          _rd_get_dyns64
  62 #define _rd_get_ehdr32          _rd_get_ehdr64
  63 #define _rd_objpad_enable32     _rd_objpad_enable64
  64 #define _rd_loadobj_iter32      _rd_loadobj_iter64
  65 #define _rd_reset32             _rd_reset64
  66 #define find_dynamic_ent32      find_dynamic_ent64
  67 #define validate_rdebug32       validate_rdebug64
  68 #define TAPlist                 APlist
  69 #define TLm_list                Lm_list
  70 #define TList                   List
  71 #define TListnode               Listnode
  72 #define MSG_SYM_BRANDOPS        MSG_SYM_BRANDOPS_64
  73 #else   /* ELF32 */
  74 #define Rt_map                  Rt_map32
  75 #define Rtld_db_priv            Rtld_db_priv32
  76 #define TAPlist                 APlist32
  77 #define TLm_list                Lm_list32
  78 #define TList                   List32
  79 #define TListnode               Listnode32
  80 #define Lm_list                 Lm_list32
  81 #define MSG_SYM_BRANDOPS        MSG_SYM_BRANDOPS_32
  82 #endif  /* _ELF64 */
  83 #else   /* _LP64 */
  84 #define TAPlist                 APlist
  85 #define TLm_list                Lm_list
  86 #define TList                   List
  87 #define TListnode               Listnode
  88 #define MSG_SYM_BRANDOPS        MSG_SYM_BRANDOPS_32
  89 #endif  /* _LP64 */
  90 
  91 /*
  92  * BrandZ added ps_pbrandname().  Many debuggers that link directly
  93  * against librtld_db.so may not implement this interface.  Hence
  94  * we won't call the function directly, instead we'll try to look it
  95  * up using the linker first and only invoke it if we find it.
  96  */
  97 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
  98     char *, size_t);
  99 
 100 rd_err_e
 101 validate_rdebug32(struct rd_agent *rap)
 102 {
 103         struct ps_prochandle    *php = rap->rd_psp;
 104         psaddr_t                db_privp;
 105         Rtld_db_priv            db_priv;
 106 
 107         if (rap->rd_rdebug == 0)
 108                 return (RD_ERR);
 109 
 110         /*
 111          * The rtld_db_priv structure contains both the traditional (exposed)
 112          * r_debug structure as well as private data only available to
 113          * this library.
 114          */
 115         db_privp = rap->rd_rdebug;
 116 
 117         /*
 118          * Verify that librtld_db & rtld are at the proper revision
 119          * levels.
 120          */
 121         if (ps_pread(php, db_privp, (char *)&db_priv,
 122             sizeof (Rtld_db_priv)) != PS_OK) {
 123                 LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
 124                     EC_ADDR(db_privp)));
 125                 return (RD_DBERR);
 126         }
 127 
 128         if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
 129             (db_priv.rtd_version > R_RTLDDB_VERSION)) {
 130                 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
 131                     db_priv.rtd_version, R_RTLDDB_VERSION));
 132                 return (RD_NOCAPAB);
 133         }
 134 
 135         /*
 136          * Is the image being examined from a core file or not.
 137          * If it is a core file then the following write will fail.
 138          */
 139         if (ps_pwrite(php, db_privp, (char *)&db_priv,
 140             sizeof (Rtld_db_priv)) != PS_OK)
 141                 rap->rd_flags |= RDF_FL_COREFILE;
 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.)  Note
 299          * that we pull in the native root here to allow for helper libraries
 300          * to be properly found from within the branded zone.
 301          */
 302         ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
 303         while ((ps_pbrandname != NULL) &&
 304             (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
 305                 const char *isa = "";
 306 
 307 #ifdef _LP64
 308                 isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
 309 #endif /* _LP64 */
 310 
 311                 if (rtld_db_helper_path[0] != '\0') {
 312                         (void) snprintf(brandlib, MAXPATHLEN,
 313                             MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
 314                             rtld_db_helper_path,
 315                             MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
 316                             brandname);
 317                 } else {
 318                         const char *nroot = zone_get_nroot();
 319 
 320                         if (nroot == NULL)
 321                                 nroot = "";
 322 
 323                         (void) snprintf(brandlib, MAXPATHLEN,
 324                             MSG_ORIG(MSG_DB_BRAND_HELPERPATH), nroot,
 325                             MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
 326                             brandname);
 327                 }
 328 
 329                 rap->rd_helper.rh_dlhandle = dlopen(brandlib,
 330                     RTLD_LAZY | RTLD_LOCAL);
 331                 if (rap->rd_helper.rh_dlhandle == NULL) {
 332                         LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
 333                             brandlib));
 334                         break;
 335                 }
 336 
 337                 rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
 338                     MSG_ORIG(MSG_SYM_BRANDOPS));
 339                 if (rap->rd_helper.rh_ops == NULL) {
 340                         LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
 341                             brandlib));
 342                         (void) dlclose(rap->rd_helper.rh_dlhandle);
 343                         rap->rd_helper.rh_dlhandle = NULL;
 344                         break;
 345                 }
 346 
 347                 rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
 348                     php);
 349                 if (rap->rd_helper.rh_data == NULL) {
 350                         LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
 351                         (void) dlclose(rap->rd_helper.rh_dlhandle);
 352                         rap->rd_helper.rh_dlhandle = NULL;
 353                         rap->rd_helper.rh_ops = NULL;
 354                         break;
 355                 }
 356 
 357                 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
 358                 break;
 359 
 360                 /* NOTREACHED */
 361         }
 362 
 363         if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
 364                 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
 365                     MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
 366                         LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
 367                             MSG_ORIG(MSG_SYM_PREINIT)));
 368                         return (RD_DBERR);
 369                 }
 370                 rap->rd_preinit = symaddr;
 371 
 372                 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
 373                     MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
 374                         LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
 375                             MSG_ORIG(MSG_SYM_POSTINIT)));
 376                         return (RD_DBERR);
 377                 }
 378                 rap->rd_postinit = symaddr;
 379 
 380                 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
 381                     MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
 382                         LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
 383                             MSG_ORIG(MSG_SYM_DLACT)));
 384                         return (RD_DBERR);
 385                 }
 386                 rap->rd_dlact = symaddr;
 387                 rap->rd_tbinder = 0;
 388         }
 389 
 390         return (RD_OK);
 391 }
 392 
 393 rd_err_e
 394 _rd_get_ehdr32(struct rd_agent *rap,
 395     psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
 396 {
 397         struct ps_prochandle    *php = rap->rd_psp;
 398         Shdr                    shdr;
 399 
 400         if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
 401                 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
 402                 return (RD_ERR);
 403         }
 404         if (phnum == NULL)
 405                 return (RD_OK);
 406 
 407         if (ehdr->e_phnum != PN_XNUM) {
 408                 *phnum = ehdr->e_phnum;
 409                 return (RD_OK);
 410         }
 411 
 412         /* deal with elf extended program headers */
 413         if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
 414                 return (RD_ERR);
 415 
 416         addr += ehdr->e_shoff;
 417         if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
 418                 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
 419                 return (RD_ERR);
 420         }
 421 
 422         if (shdr.sh_info == 0)
 423                 return (RD_ERR);
 424 
 425         *phnum = shdr.sh_info;
 426         return (RD_OK);
 427 }
 428 
 429 rd_err_e
 430 _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
 431 {
 432         struct ps_prochandle    *php = rap->rd_psp;
 433         rd_err_e                err;
 434         uint_t                  phnum;
 435         Ehdr                    ehdr;
 436         Phdr                    phdr;
 437         Dyn                     *dynp;
 438         int                     i;
 439 
 440         /* We only need to muck with dyn elements for ET_DYN objects */
 441         if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
 442                 return (err);
 443 
 444         for (i = 0; i < phnum; i++) {
 445                 psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
 446                 if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
 447                         LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
 448                         return (RD_ERR);
 449                 }
 450                 if (phdr.p_type == PT_DYNAMIC)
 451                         break;
 452         }
 453         if (i == phnum)
 454                 return (RD_ERR);
 455 
 456         if ((dynp = malloc(phdr.p_filesz)) == NULL)
 457                 return (RD_ERR);
 458         if (ehdr.e_type == ET_DYN)
 459                 phdr.p_vaddr += addr;
 460         if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
 461                 free(dynp);
 462                 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
 463                     EC_ADDR(phdr.p_vaddr)));
 464                 return (RD_ERR);
 465         }
 466 
 467         *dynpp = dynp;
 468         if (dynpp_sz != NULL)
 469                 *dynpp_sz = phdr.p_filesz;
 470         return (RD_OK);
 471 }
 472 
 473 rd_err_e
 474 _rd_event_enable32(rd_agent_t *rap, int onoff)
 475 {
 476         struct ps_prochandle    *php = rap->rd_psp;
 477         Rtld_db_priv            rdb;
 478 
 479         LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
 480         /*
 481          * Tell the debugged process that debugging is occuring
 482          * This will enable the storing of event messages so that
 483          * the can be gathered by the debugger.
 484          */
 485         if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
 486             sizeof (Rtld_db_priv)) != PS_OK) {
 487                 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
 488                     EC_ADDR((uintptr_t)&rdb)));
 489                 return (RD_DBERR);
 490         }
 491 
 492         if (onoff)
 493                 rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
 494         else
 495                 rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
 496 
 497         if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
 498             sizeof (Rtld_db_priv)) != PS_OK) {
 499                 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
 500                     EC_ADDR((uintptr_t)&rdb)));
 501                 return (RD_DBERR);
 502         }
 503 
 504         return (RD_OK);
 505 }
 506 
 507 
 508 rd_err_e
 509 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
 510 {
 511         Rtld_db_priv    rdb;
 512 
 513         if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
 514             sizeof (Rtld_db_priv)) != PS_OK) {
 515                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
 516                     EC_ADDR(rap->rd_rdebug)));
 517                 return (RD_DBERR);
 518         }
 519         emsg->type = rdb.rtd_rdebug.r_rdevent;
 520         if (emsg->type == RD_DLACTIVITY) {
 521                 switch (rdb.rtd_rdebug.r_state) {
 522                         case RT_CONSISTENT:
 523                                 emsg->u.state = RD_CONSISTENT;
 524                                 break;
 525                         case RT_ADD:
 526                                 emsg->u.state = RD_ADD;
 527                                 break;
 528                         case RT_DELETE:
 529                                 emsg->u.state = RD_DELETE;
 530                                 break;
 531                 }
 532         } else
 533                 emsg->u.state = RD_NOSTATE;
 534 
 535         LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
 536             emsg->type, emsg->u.state));
 537 
 538         return (RD_OK);
 539 }
 540 
 541 
 542 rd_err_e
 543 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
 544 {
 545         Rtld_db_priv            db_priv;
 546         struct ps_prochandle    *php = rap->rd_psp;
 547 
 548         LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
 549 
 550         if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
 551             sizeof (Rtld_db_priv)) != PS_OK) {
 552                 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
 553                     EC_ADDR(rap->rd_rtlddbpriv)));
 554                 return (RD_DBERR);
 555         }
 556 #if     defined(_LP64) && !defined(_ELF64)
 557         /*LINTED*/
 558         db_priv.rtd_objpad = (uint32_t)padsize;
 559 #else
 560         db_priv.rtd_objpad = padsize;
 561 #endif
 562         if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
 563             sizeof (Rtld_db_priv)) != PS_OK) {
 564                 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
 565                     EC_ADDR(rap->rd_rtlddbpriv)));
 566                 return (RD_DBERR);
 567         }
 568         return (RD_OK);
 569 }
 570 
 571 static rd_err_e
 572 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
 573         rl_iter_f *cb, void *client_data, uint_t *abort_iterp)
 574 {
 575         while (lmaddr) {
 576                 Rt_map          rmap;
 577                 rd_loadobj_t    lobj;
 578                 int             i;
 579                 ulong_t         off;
 580                 Ehdr            ehdr;
 581                 Phdr            phdr;
 582 
 583                 if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
 584                     sizeof (Rt_map)) != PS_OK) {
 585                         LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
 586                         return (RD_DBERR);
 587                 }
 588 
 589                 /*
 590                  * As of 'VERSION5' we only report objects
 591                  * which have been fully relocated.  While the maps
 592                  * might be in a consistent state - if a object hasn't
 593                  * been relocated - it's not really ready for the debuggers
 594                  * to examine.  This is mostly due to the fact that we
 595                  * might still be mucking with the text-segment, if
 596                  * we are - we could conflict with any break-points
 597                  * the debuggers might have set.
 598                  */
 599                 if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
 600                         if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
 601                                 lmaddr = (psaddr_t)NEXT(&rmap);
 602                                 continue;
 603                         }
 604                 }
 605 
 606                 lobj.rl_base = (psaddr_t)ADDR(&rmap);
 607                 lobj.rl_flags = 0;
 608                 lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
 609                 if ((rap->rd_helper.rh_ops != NULL) &&
 610                     (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
 611                         lobj.rl_lmident =
 612                             rap->rd_helper.rh_ops->rho_lmid;
 613                 else
 614                         lobj.rl_lmident = ident;
 615 
 616                 /*
 617                  * refnameaddr is only valid from a core file
 618                  * which is VERSION3 or greater.
 619                  */
 620                 if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
 621                         lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
 622                         lobj.rl_bend = 0;
 623                         lobj.rl_padstart = 0;
 624                         lobj.rl_padend = 0;
 625                 } else {
 626                         lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
 627                         lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
 628                         lobj.rl_padstart = PADSTART(&rmap);
 629                         lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
 630 
 631                 }
 632 
 633                 if (rtld_db_version >= RD_VERSION2)
 634                         if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
 635                                 lobj.rl_flags |= RD_FLG_MEM_OBJECT;
 636                 if (rtld_db_version >= RD_VERSION2) {
 637                         lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
 638                 }
 639 
 640                 if (rtld_db_version >= RD_VERSION4)
 641                         lobj.rl_tlsmodid = TLSMODID(&rmap);
 642 
 643                 /*
 644                  * Look for beginning of data segment.
 645                  *
 646                  * NOTE: the data segment can only be found for full
 647                  *      processes and not from core images.
 648                  */
 649                 lobj.rl_data_base = 0;
 650                 if (rap->rd_flags & RDF_FL_COREFILE)
 651                         lobj.rl_data_base = 0;
 652                 else {
 653                         off = ADDR(&rmap);
 654                         if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
 655                             sizeof (Ehdr)) != PS_OK) {
 656                                 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
 657                                 return (RD_DBERR);
 658                         }
 659                         off += sizeof (Ehdr);
 660                         for (i = 0; i < ehdr.e_phnum; i++) {
 661                                 if (ps_pread(rap->rd_psp, off, (char *)&phdr,
 662                                     sizeof (Phdr)) != PS_OK) {
 663                                         LOG(ps_plog(MSG_ORIG(
 664                                             MSG_DB_LKMAPFAIL)));
 665                                         return (RD_DBERR);
 666                                 }
 667                                 if ((phdr.p_type == PT_LOAD) &&
 668                                     (phdr.p_flags & PF_W)) {
 669                                         lobj.rl_data_base = phdr.p_vaddr;
 670                                         if (ehdr.e_type == ET_DYN)
 671                                                 lobj.rl_data_base +=
 672                                                     ADDR(&rmap);
 673                                         break;
 674                                 }
 675                                 off += ehdr.e_phentsize;
 676                         }
 677                 }
 678 
 679                 /*
 680                  * When we transfer control to the client we free the
 681                  * lock and re-atain it after we've returned from the
 682                  * client.  This is to avoid any deadlock situations.
 683                  */
 684                 LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
 685                     EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
 686                 RDAGUNLOCK(rap);
 687                 if ((*cb)(&lobj, client_data) == 0) {
 688                         LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
 689                         RDAGLOCK(rap);
 690                         *abort_iterp = 1;
 691                         break;
 692                 }
 693                 RDAGLOCK(rap);
 694                 lmaddr = (psaddr_t)NEXT(&rmap);
 695         }
 696         return (RD_OK);
 697 }
 698 
 699 
 700 static rd_err_e
 701 _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data,
 702     uint_t *abort_iterp)
 703 {
 704         Rtld_db_priv    db_priv;
 705         TAPlist         apl;
 706         uintptr_t       datap, nitems;
 707         Addr            addr;
 708         rd_err_e        rc;
 709 
 710         LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
 711             client_data));
 712 
 713         /*
 714          * First, determine whether the link-map information has been
 715          * established.  Some debuggers have made an initial call to this
 716          * function with a null call back function (cb), but expect a
 717          * RD_NOMAPS error return rather than a RD_ERR return when the
 718          * link-maps aren't available.
 719          */
 720         if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
 721             sizeof (Rtld_db_priv)) != PS_OK) {
 722                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
 723                     EC_ADDR(rap->rd_rtlddbpriv)));
 724                 return (RD_DBERR);
 725         }
 726 
 727         if (db_priv.rtd_dynlmlst == NULL) {
 728                 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
 729                     EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
 730                 return (RD_NOMAPS);
 731         }
 732 
 733         if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr,
 734             sizeof (Addr)) != PS_OK) {
 735                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
 736                     EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
 737                 return (RD_DBERR);
 738         }
 739 
 740         if (addr == NULL) {
 741                 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
 742                     EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
 743                 return (RD_NOMAPS);
 744         }
 745 
 746         /*
 747          * Having determined we have link-maps, ensure we have an iterator
 748          * call back function.
 749          */
 750         if (cb == NULL) {
 751                 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
 752                 return (RD_ERR);
 753         }
 754 
 755         /*
 756          * As of VERSION6, rtd_dynlmlst points to an APlist.  Prior to VERSION6
 757          * rtd_dynlmlst pointed to a List.  But, there was a window where the
 758          * version was not incremented, and this must be worked around by
 759          * interpreting the APlist data.  Read the initial APlist information.
 760          */
 761         if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl,
 762             sizeof (TAPlist)) != PS_OK) {
 763                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
 764                     EC_ADDR((uintptr_t)addr)));
 765                 return (RD_DBERR);
 766         }
 767 
 768         /*
 769          * The rtd_dynlmlst change from a List to an APlist occurred under
 770          * 6801536 in snv_112.  However, this change neglected to preserve
 771          * backward compatibility by maintaining List processing and using a
 772          * version increment to detect the change.  6862967, intergrated in
 773          * snv_121 corrects the version detection.  However, to catch objects
 774          * built between these releases, we look at the first element of the
 775          * APlist.  apl_arritems indicates the number of APlist items that are
 776          * available.  This was originally initialized with a AL_CNT_DYNLIST
 777          * value of 2 (one entry for LM_ID_BASE and one entry for LM_ID_LDSO).
 778          * It is possible that the use of an auditor results in an additional
 779          * link-map list, in which case the original apl_arritems would have
 780          * been doubled.
 781          *
 782          * Therefore, if the debugging verion is VERSION6, or the apl_arritems
 783          * entry has a value less than or equal to 4 and the debugging version
 784          * is VERSION5, then we process APlists.  Otherwise, fall back to List
 785          * processing.
 786          */
 787         if ((rap->rd_rdebugvers >= R_RTLDDB_VERSION6) ||
 788             ((rap->rd_rdebugvers == R_RTLDDB_VERSION5) &&
 789             (apl.apl_arritems <= 4))) {
 790                 /*
 791                  * Iterate through each apl.ap_data[] entry.
 792                  */
 793                 for (datap = (uintptr_t)((char *)(uintptr_t)addr +
 794                     ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0;
 795                     nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) {
 796                         TLm_list        lm;
 797                         ulong_t         ident;
 798 
 799                         /*
 800                          * Obtain the Lm_list address for this apl.ap_data[]
 801                          * entry.
 802                          */
 803                         if (ps_pread(rap->rd_psp, (psaddr_t)datap,
 804                             (char *)&addr, sizeof (Addr)) != PS_OK) {
 805                                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
 806                                     EC_ADDR(datap)));
 807                                 return (RD_DBERR);
 808                         }
 809 
 810                         /*
 811                          * Obtain the Lm_list data for this Lm_list address.
 812                          */
 813                         if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm,
 814                             sizeof (TLm_list)) != PS_OK) {
 815                                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6),
 816                                     EC_ADDR((uintptr_t)addr)));
 817                                 return (RD_DBERR);
 818                         }
 819 
 820                         /*
 821                          * Determine IDENT of current LM_LIST
 822                          */
 823                         if (lm.lm_flags & LML_FLG_BASELM)
 824                                 ident = LM_ID_BASE;
 825                         else if (lm.lm_flags & LML_FLG_RTLDLM)
 826                                 ident = LM_ID_LDSO;
 827                         else
 828                                 ident = (ulong_t)addr;
 829 
 830                         if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head,
 831                             cb, client_data, abort_iterp)) != RD_OK)
 832                                 return (rc);
 833 
 834                         if (*abort_iterp != 0)
 835                                 break;
 836                 }
 837         } else {
 838                 TList           list;
 839                 TListnode       lnode;
 840                 Addr            lnp;
 841 
 842                 /*
 843                  * Re-read the dynlmlst address to obtain a List structure.
 844                  */
 845                 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst,
 846                     (char *)&list, sizeof (TList)) != PS_OK) {
 847                         LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
 848                             EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
 849                         return (RD_DBERR);
 850                 }
 851 
 852                 /*
 853                  * Iterate through the link-map list.
 854                  */
 855                 for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
 856                         Lm_list lml;
 857                         ulong_t ident;
 858 
 859                         /*
 860                          * Iterate through the List of Lm_list's.
 861                          */
 862                         if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
 863                             sizeof (TListnode)) != PS_OK) {
 864                                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
 865                                     EC_ADDR(lnp)));
 866                                         return (RD_DBERR);
 867                         }
 868 
 869                         if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data,
 870                             (char *)&lml, sizeof (Lm_list)) != PS_OK) {
 871                                 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
 872                                     EC_ADDR((uintptr_t)lnode.data)));
 873                                         return (RD_DBERR);
 874                         }
 875 
 876                         /*
 877                          * Determine IDENT of current LM_LIST
 878                          */
 879                         if (lml.lm_flags & LML_FLG_BASELM)
 880                                 ident = LM_ID_BASE;
 881                         else if (lml.lm_flags & LML_FLG_RTLDLM)
 882                                 ident = LM_ID_LDSO;
 883                         else
 884                                 ident = (unsigned long)lnode.data;
 885 
 886                         if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
 887                             cb, client_data, abort_iterp)) != RD_OK)
 888                                 return (rc);
 889 
 890                         if (*abort_iterp != 0)
 891                                 break;
 892                 }
 893         }
 894 
 895         return (rc);
 896 }
 897 
 898 rd_err_e
 899 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
 900 {
 901         rd_err_e        rc, rc_brand = RD_OK;
 902         uint_t          abort_iter = 0;
 903 
 904         /* First iterate over the native target objects */
 905         rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter);
 906         if (abort_iter != 0)
 907                 return (rc);
 908 
 909         /* Then iterate over any branded objects. */
 910         if ((rap->rd_helper.rh_ops != NULL) &&
 911             (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL))
 912                 rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter(
 913                     rap->rd_helper.rh_data, cb, client_data);
 914 
 915         rc = (rc != RD_OK) ? rc : rc_brand;
 916         return (rc);
 917 }