17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59acbbeafSnn * Common Development and Distribution License (the "License"). 69acbbeafSnn * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*22872efbSedp * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <proc_service.h> 317c478bd9Sstevel@tonic-gate #include <link.h> 327c478bd9Sstevel@tonic-gate #include <rtld_db.h> 337c478bd9Sstevel@tonic-gate #include <rtld.h> 347c478bd9Sstevel@tonic-gate #include <_rtld_db.h> 357c478bd9Sstevel@tonic-gate #include <msg.h> 369acbbeafSnn #include <limits.h> 379acbbeafSnn #include <string.h> 389acbbeafSnn #include <sys/param.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * 64-bit builds are going to compile this module twice, the 427c478bd9Sstevel@tonic-gate * second time with _ELF64 defined. These defines should make 437c478bd9Sstevel@tonic-gate * all the necessary adjustments to the code. 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate #ifdef _LP64 467c478bd9Sstevel@tonic-gate #ifdef _ELF64 477c478bd9Sstevel@tonic-gate #define _rd_event_enable32 _rd_event_enable64 487c478bd9Sstevel@tonic-gate #define _rd_event_getmsg32 _rd_event_getmsg64 49*22872efbSedp #define _rd_get_dyns32 _rd_get_dyns64 50*22872efbSedp #define _rd_get_ehdr32 _rd_get_ehdr64 517c478bd9Sstevel@tonic-gate #define _rd_objpad_enable32 _rd_objpad_enable64 527c478bd9Sstevel@tonic-gate #define _rd_loadobj_iter32 _rd_loadobj_iter64 53*22872efbSedp #define _rd_reset32 _rd_reset64 547c478bd9Sstevel@tonic-gate #define find_dynamic_ent32 find_dynamic_ent64 55*22872efbSedp #define validate_rdebug32 validate_rdebug64 567c478bd9Sstevel@tonic-gate #define TList List 577c478bd9Sstevel@tonic-gate #define TListnode Listnode 58*22872efbSedp #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS64 597c478bd9Sstevel@tonic-gate #else /* ELF32 */ 607c478bd9Sstevel@tonic-gate #define Rt_map Rt_map32 617c478bd9Sstevel@tonic-gate #define Rtld_db_priv Rtld_db_priv32 627c478bd9Sstevel@tonic-gate #define TList List32 637c478bd9Sstevel@tonic-gate #define TListnode Listnode32 647c478bd9Sstevel@tonic-gate #define Lm_list Lm_list32 65*22872efbSedp #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS32 667c478bd9Sstevel@tonic-gate #endif /* _ELF64 */ 677c478bd9Sstevel@tonic-gate #else /* _LP64 */ 687c478bd9Sstevel@tonic-gate #define TList List 697c478bd9Sstevel@tonic-gate #define TListnode Listnode 70*22872efbSedp #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS32 717c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 727c478bd9Sstevel@tonic-gate 735eae5a6fSedp /* 745eae5a6fSedp * BrandZ added ps_pbrandname(). Many debuggers that link directly 755eae5a6fSedp * against librtld_db.so may not implement this interface. Hence 765eae5a6fSedp * we won't call the function directly, instead we'll try to look it 775eae5a6fSedp * up using the linker first and only invoke it if we find it. 785eae5a6fSedp */ 795eae5a6fSedp typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *, 805eae5a6fSedp char *, size_t); 815eae5a6fSedp 82*22872efbSedp rd_err_e 83*22872efbSedp validate_rdebug32(struct rd_agent *rap) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 867c478bd9Sstevel@tonic-gate psaddr_t db_privp; 877c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if (rap->rd_rdebug == 0) 907c478bd9Sstevel@tonic-gate return (RD_ERR); 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * The rtld_db_priv structure contains both the traditional (exposed) 937c478bd9Sstevel@tonic-gate * r_debug structure as well as private data only available to 947c478bd9Sstevel@tonic-gate * this library. 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate db_privp = rap->rd_rdebug; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Verify that librtld_db & rtld are at the proper revision 1007c478bd9Sstevel@tonic-gate * levels. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate if (ps_pread(php, db_privp, (char *)&db_priv, 1037c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 1047c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1), 1059acbbeafSnn EC_ADDR(db_privp))); 1067c478bd9Sstevel@tonic-gate return (RD_DBERR); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate if ((db_priv.rtd_version < R_RTLDDB_VERSION1) || 1107c478bd9Sstevel@tonic-gate (db_priv.rtd_version > R_RTLDDB_VERSION)) { 1117c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 1129acbbeafSnn db_priv.rtd_version, R_RTLDDB_VERSION)); 1137c478bd9Sstevel@tonic-gate return (RD_NOCAPAB); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * Is the image being examined from a core file or not. 1187c478bd9Sstevel@tonic-gate * If it is a core file then the following write will fail. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate if (ps_pwrite(php, db_privp, (char *)&db_priv, 1217c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) 1227c478bd9Sstevel@tonic-gate rap->rd_flags |= RDF_FL_COREFILE; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * If this *is not* a core file then rtld_db & ld.so.1 are 1267c478bd9Sstevel@tonic-gate * considered tightly coupled. If the versions of our private 1277c478bd9Sstevel@tonic-gate * data structures don't match - fail! 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate if (((rap->rd_flags & RDF_FL_COREFILE) == 0) && 1307c478bd9Sstevel@tonic-gate (db_priv.rtd_version != R_RTLDDB_VERSION)) { 1317c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 1329acbbeafSnn db_priv.rtd_version, R_RTLDDB_VERSION)); 1337c478bd9Sstevel@tonic-gate return (RD_NOCAPAB); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate rap->rd_rdebugvers = db_priv.rtd_version; 1377c478bd9Sstevel@tonic-gate rap->rd_rtlddbpriv = db_privp; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug), 1409acbbeafSnn R_RTLDDB_VERSION, rap->rd_rdebugvers, 1419acbbeafSnn rap->rd_flags & RDF_FL_COREFILE)); 1427c478bd9Sstevel@tonic-gate return (RD_OK); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate rd_err_e 1477c478bd9Sstevel@tonic-gate find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr, 1487c478bd9Sstevel@tonic-gate Xword dyntag, Dyn *dyn) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 1517c478bd9Sstevel@tonic-gate Dyn d; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate d.d_tag = DT_NULL; 1547c478bd9Sstevel@tonic-gate do { 1557c478bd9Sstevel@tonic-gate if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) != 1567c478bd9Sstevel@tonic-gate PS_OK) { 1577c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4), 1589acbbeafSnn EC_ADDR(dynaddr))); 1597c478bd9Sstevel@tonic-gate return (RD_DBERR); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate dynaddr += sizeof (d); 1627c478bd9Sstevel@tonic-gate if (d.d_tag == dyntag) 1637c478bd9Sstevel@tonic-gate break; 1647c478bd9Sstevel@tonic-gate } while (d.d_tag != DT_NULL); 1657c478bd9Sstevel@tonic-gate if (d.d_tag == dyntag) { 1667c478bd9Sstevel@tonic-gate *dyn = d; 1677c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag), 1687c478bd9Sstevel@tonic-gate EC_ADDR(d.d_un.d_val))); 1697c478bd9Sstevel@tonic-gate return (RD_OK); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag))); 1727c478bd9Sstevel@tonic-gate return (RD_DBERR); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1759acbbeafSnn extern char rtld_db_helper_path[MAXPATHLEN]; 1769acbbeafSnn 1777c478bd9Sstevel@tonic-gate rd_err_e 1787c478bd9Sstevel@tonic-gate _rd_reset32(struct rd_agent *rap) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate psaddr_t symaddr; 1817c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 1827c478bd9Sstevel@tonic-gate const auxv_t *auxvp = NULL; 1837c478bd9Sstevel@tonic-gate rd_err_e rc = RD_OK; 1849acbbeafSnn char brandname[MAXPATHLEN]; 1859acbbeafSnn char brandlib[MAXPATHLEN]; 1865eae5a6fSedp ps_pbrandname_fp_t ps_pbrandname; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * librtld_db attempts three different methods to find 1907c478bd9Sstevel@tonic-gate * the r_debug structure which is required to 1917c478bd9Sstevel@tonic-gate * initialize itself. The methods are: 1927c478bd9Sstevel@tonic-gate * method1: 1937c478bd9Sstevel@tonic-gate * entirely independent of any text segment 1947c478bd9Sstevel@tonic-gate * and relies on the AT_SUN_LDDATA auxvector 1957c478bd9Sstevel@tonic-gate * to find the ld.so.1::rdebug structure. 1967c478bd9Sstevel@tonic-gate * method2: 1977c478bd9Sstevel@tonic-gate * lookup symbols in ld.so.1's symbol table 1987c478bd9Sstevel@tonic-gate * to find the r_debug symbol. 1997c478bd9Sstevel@tonic-gate * method3: 2007c478bd9Sstevel@tonic-gate * (old dbx method) dependent upon the 2017c478bd9Sstevel@tonic-gate * text segment/symbol table of the 2027c478bd9Sstevel@tonic-gate * executable and not ld.so.1. We lookup the 2037c478bd9Sstevel@tonic-gate * _DYNAMIC symbol in the executable and look for 2047c478bd9Sstevel@tonic-gate * the DT_DEBUG entry in the .dynamic table. This 2057c478bd9Sstevel@tonic-gate * points to rdebug. 2067c478bd9Sstevel@tonic-gate * 2077c478bd9Sstevel@tonic-gate * If none of that works - we fail. 2087c478bd9Sstevel@tonic-gate */ 2097c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel)); 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * Method1 2127c478bd9Sstevel@tonic-gate * 2137c478bd9Sstevel@tonic-gate * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA 2147c478bd9Sstevel@tonic-gate */ 2159acbbeafSnn 2167c478bd9Sstevel@tonic-gate if (ps_pauxv(php, &auxvp) != PS_OK) { 2177c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV))); 2187c478bd9Sstevel@tonic-gate rc = RD_ERR; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate rap->rd_rdebug = 0; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (auxvp != NULL) { 2247c478bd9Sstevel@tonic-gate rc = RD_ERR; 2257c478bd9Sstevel@tonic-gate while (auxvp->a_type != AT_NULL) { 2267c478bd9Sstevel@tonic-gate if (auxvp->a_type == AT_SUN_LDDATA) { 2277c478bd9Sstevel@tonic-gate /* LINTED */ 2287c478bd9Sstevel@tonic-gate rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr; 2297c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA), 2307c478bd9Sstevel@tonic-gate rap->rd_rdebug)); 231*22872efbSedp rc = validate_rdebug32(rap); 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate auxvp++; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * method2 - look for r_rdebug symbol in ld.so.1 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * If the AT_SUN_LDDATA auxv vector is not present 2447c478bd9Sstevel@tonic-gate * fall back on doing a symlookup of 2457c478bd9Sstevel@tonic-gate * the r_debug symbol. This is for backward 2467c478bd9Sstevel@tonic-gate * compatiblity with older OS's 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA))); 2497c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG), 2507c478bd9Sstevel@tonic-gate &symaddr) != PS_OK) { 2517c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 2529acbbeafSnn MSG_ORIG(MSG_SYM_DEBUG))); 2537c478bd9Sstevel@tonic-gate rc = RD_DBERR; 2547c478bd9Sstevel@tonic-gate } else { 2557c478bd9Sstevel@tonic-gate rap->rd_rdebug = symaddr; 2567c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG), 2579acbbeafSnn EC_ADDR(symaddr))); 258*22872efbSedp rc = validate_rdebug32(rap); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * method3 - find DT_DEBUG in the executables .dynamic section. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2677c478bd9Sstevel@tonic-gate Dyn dyn; 2687c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_EXEC, 2697c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) { 2707c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC))); 2717c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2727c478bd9Sstevel@tonic-gate return (rc); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn); 2757c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2767c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2777c478bd9Sstevel@tonic-gate return (rc); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate rap->rd_rdebug = dyn.d_un.d_ptr; 280*22872efbSedp rc = validate_rdebug32(rap); 2817c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2827c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2837c478bd9Sstevel@tonic-gate return (rc); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2879acbbeafSnn /* 288*22872efbSedp * If we are debugging a branded executable, load the appropriate 289*22872efbSedp * helper library, and call its initialization routine. Being unable 290*22872efbSedp * to load the helper library is not a critical error. (Hopefully 291*22872efbSedp * we'll still be able to access some objects in the target.) 2929acbbeafSnn */ 2935eae5a6fSedp ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname"); 294*22872efbSedp while ((ps_pbrandname != NULL) && 2955eae5a6fSedp (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) { 2969acbbeafSnn const char *isa = ""; 2979acbbeafSnn 298*22872efbSedp #ifdef _LP64 2999acbbeafSnn isa = MSG_ORIG(MSG_DB_64BIT_PREFIX); 300*22872efbSedp #endif /* _LP64 */ 3019acbbeafSnn 3029acbbeafSnn if (rtld_db_helper_path[0] != '\0') 3039acbbeafSnn (void) snprintf(brandlib, MAXPATHLEN, 3049acbbeafSnn MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX), 3059acbbeafSnn rtld_db_helper_path, 3069acbbeafSnn MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 3079acbbeafSnn brandname); 3089acbbeafSnn else 3099acbbeafSnn (void) snprintf(brandlib, MAXPATHLEN, 3109acbbeafSnn MSG_ORIG(MSG_DB_BRAND_HELPERPATH), 3119acbbeafSnn MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 3129acbbeafSnn brandname); 3139acbbeafSnn 314*22872efbSedp rap->rd_helper.rh_dlhandle = dlopen(brandlib, 315*22872efbSedp RTLD_LAZY | RTLD_LOCAL); 316*22872efbSedp if (rap->rd_helper.rh_dlhandle == NULL) { 3179acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED), 3189acbbeafSnn brandlib)); 319*22872efbSedp break; 3209acbbeafSnn } 3219acbbeafSnn 322*22872efbSedp rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle, 323*22872efbSedp MSG_ORIG(MSG_SYM_BRANDOPS)); 324*22872efbSedp if (rap->rd_helper.rh_ops == NULL) { 3259acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS), 3269acbbeafSnn brandlib)); 327*22872efbSedp (void) dlclose(rap->rd_helper.rh_dlhandle); 328*22872efbSedp rap->rd_helper.rh_dlhandle = NULL; 329*22872efbSedp break; 3309acbbeafSnn } 3319acbbeafSnn 332*22872efbSedp rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap, 333*22872efbSedp php); 3349acbbeafSnn if (rap->rd_helper.rh_data == NULL) { 3359acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED))); 3369acbbeafSnn (void) dlclose(rap->rd_helper.rh_dlhandle); 3379acbbeafSnn rap->rd_helper.rh_dlhandle = NULL; 3389acbbeafSnn rap->rd_helper.rh_ops = NULL; 339*22872efbSedp break; 340*22872efbSedp } 341*22872efbSedp 342*22872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname)); 343*22872efbSedp break; 3449acbbeafSnn } 3459acbbeafSnn 3467c478bd9Sstevel@tonic-gate if ((rap->rd_flags & RDF_FL_COREFILE) == 0) { 3477c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 3487c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) { 3497c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 3509acbbeafSnn MSG_ORIG(MSG_SYM_PREINIT))); 3517c478bd9Sstevel@tonic-gate return (RD_DBERR); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate rap->rd_preinit = symaddr; 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 3567c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) { 3577c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 3589acbbeafSnn MSG_ORIG(MSG_SYM_POSTINIT))); 3597c478bd9Sstevel@tonic-gate return (RD_DBERR); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate rap->rd_postinit = symaddr; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, 3647c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) { 3657c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 3669acbbeafSnn MSG_ORIG(MSG_SYM_DLACT))); 3677c478bd9Sstevel@tonic-gate return (RD_DBERR); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate rap->rd_dlact = symaddr; 3707c478bd9Sstevel@tonic-gate rap->rd_tbinder = 0; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate return (RD_OK); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 376*22872efbSedp rd_err_e 377*22872efbSedp _rd_get_ehdr32(struct rd_agent *rap, 378*22872efbSedp psaddr_t addr, Ehdr *ehdr, uint_t *phnum) 379*22872efbSedp { 380*22872efbSedp struct ps_prochandle *php = rap->rd_psp; 381*22872efbSedp Shdr shdr; 382*22872efbSedp 383*22872efbSedp if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) { 384*22872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 385*22872efbSedp return (RD_ERR); 386*22872efbSedp } 387*22872efbSedp if (phnum == NULL) 388*22872efbSedp return (RD_OK); 389*22872efbSedp 390*22872efbSedp if (ehdr->e_phnum != PN_XNUM) { 391*22872efbSedp *phnum = ehdr->e_phnum; 392*22872efbSedp return (RD_OK); 393*22872efbSedp } 394*22872efbSedp 395*22872efbSedp /* deal with elf extended program headers */ 396*22872efbSedp if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr))) 397*22872efbSedp return (RD_ERR); 398*22872efbSedp 399*22872efbSedp addr += ehdr->e_shoff; 400*22872efbSedp if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) { 401*22872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 402*22872efbSedp return (RD_ERR); 403*22872efbSedp } 404*22872efbSedp 405*22872efbSedp if (shdr.sh_info == 0) 406*22872efbSedp return (RD_ERR); 407*22872efbSedp 408*22872efbSedp *phnum = shdr.sh_info; 409*22872efbSedp return (RD_OK); 410*22872efbSedp } 411*22872efbSedp 412*22872efbSedp rd_err_e 413*22872efbSedp _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz) 414*22872efbSedp { 415*22872efbSedp struct ps_prochandle *php = rap->rd_psp; 416*22872efbSedp rd_err_e err; 417*22872efbSedp uint_t phnum; 418*22872efbSedp Ehdr ehdr; 419*22872efbSedp Phdr phdr; 420*22872efbSedp Dyn *dynp; 421*22872efbSedp int i; 422*22872efbSedp 423*22872efbSedp /* We only need to muck with dyn elements for ET_DYN objects */ 424*22872efbSedp if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK) 425*22872efbSedp return (err); 426*22872efbSedp 427*22872efbSedp for (i = 0; i < phnum; i++) { 428*22872efbSedp psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize); 429*22872efbSedp if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) { 430*22872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a))); 431*22872efbSedp return (RD_ERR); 432*22872efbSedp } 433*22872efbSedp if (phdr.p_type == PT_DYNAMIC) 434*22872efbSedp break; 435*22872efbSedp } 436*22872efbSedp if (i == phnum) 437*22872efbSedp return (RD_ERR); 438*22872efbSedp 439*22872efbSedp if ((dynp = malloc(phdr.p_filesz)) == NULL) 440*22872efbSedp return (RD_ERR); 441*22872efbSedp if (ehdr.e_type == ET_DYN) 442*22872efbSedp phdr.p_vaddr += addr; 443*22872efbSedp if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) { 444*22872efbSedp free(dynp); 445*22872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), 446*22872efbSedp EC_ADDR(phdr.p_vaddr))); 447*22872efbSedp return (RD_ERR); 448*22872efbSedp } 449*22872efbSedp 450*22872efbSedp *dynpp = dynp; 451*22872efbSedp *dynpp_sz = phdr.p_filesz; 452*22872efbSedp return (RD_OK); 453*22872efbSedp } 454*22872efbSedp 4557c478bd9Sstevel@tonic-gate rd_err_e 4567c478bd9Sstevel@tonic-gate _rd_event_enable32(rd_agent_t *rap, int onoff) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 4597c478bd9Sstevel@tonic-gate Rtld_db_priv rdb; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff)); 4627c478bd9Sstevel@tonic-gate /* 4637c478bd9Sstevel@tonic-gate * Tell the debugged process that debugging is occuring 4647c478bd9Sstevel@tonic-gate * This will enable the storing of event messages so that 4657c478bd9Sstevel@tonic-gate * the can be gathered by the debugger. 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate if (ps_pread(php, rap->rd_rdebug, (char *)&rdb, 4687c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4697c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1), 4707c478bd9Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb))); 4717c478bd9Sstevel@tonic-gate return (RD_DBERR); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (onoff) 4757c478bd9Sstevel@tonic-gate rdb.rtd_rdebug.r_flags |= RD_FL_DBG; 4767c478bd9Sstevel@tonic-gate else 4777c478bd9Sstevel@tonic-gate rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb, 4807c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4817c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1), 4827c478bd9Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb))); 4837c478bd9Sstevel@tonic-gate return (RD_DBERR); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate return (RD_OK); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate rd_err_e 4917c478bd9Sstevel@tonic-gate _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg) 4927c478bd9Sstevel@tonic-gate { 4937c478bd9Sstevel@tonic-gate Rtld_db_priv rdb; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb, 4967c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4977c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2), 4987c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rdebug))); 4997c478bd9Sstevel@tonic-gate return (RD_DBERR); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate emsg->type = rdb.rtd_rdebug.r_rdevent; 5027c478bd9Sstevel@tonic-gate if (emsg->type == RD_DLACTIVITY) { 5037c478bd9Sstevel@tonic-gate switch (rdb.rtd_rdebug.r_state) { 5047c478bd9Sstevel@tonic-gate case RT_CONSISTENT: 5057c478bd9Sstevel@tonic-gate emsg->u.state = RD_CONSISTENT; 5067c478bd9Sstevel@tonic-gate break; 5077c478bd9Sstevel@tonic-gate case RT_ADD: 5087c478bd9Sstevel@tonic-gate emsg->u.state = RD_ADD; 5097c478bd9Sstevel@tonic-gate break; 5107c478bd9Sstevel@tonic-gate case RT_DELETE: 5117c478bd9Sstevel@tonic-gate emsg->u.state = RD_DELETE; 5127c478bd9Sstevel@tonic-gate break; 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } else 5157c478bd9Sstevel@tonic-gate emsg->u.state = RD_NOSTATE; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel, 5189acbbeafSnn emsg->type, emsg->u.state)); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate return (RD_OK); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate rd_err_e 5257c478bd9Sstevel@tonic-gate _rd_objpad_enable32(struct rd_agent *rap, size_t padsize) 5267c478bd9Sstevel@tonic-gate { 5277c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 5287c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize))); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv, 5337c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 5347c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3), 5357c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 5367c478bd9Sstevel@tonic-gate return (RD_DBERR); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate #if defined(_LP64) && !defined(_ELF64) 5397c478bd9Sstevel@tonic-gate /*LINTED*/ 5407c478bd9Sstevel@tonic-gate db_priv.rtd_objpad = (uint32_t)padsize; 5417c478bd9Sstevel@tonic-gate #else 5427c478bd9Sstevel@tonic-gate db_priv.rtd_objpad = padsize; 5437c478bd9Sstevel@tonic-gate #endif 5447c478bd9Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv, 5457c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 5467c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2), 5477c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 5487c478bd9Sstevel@tonic-gate return (RD_DBERR); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate return (RD_OK); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate static rd_err_e 5547c478bd9Sstevel@tonic-gate iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr, 5557c478bd9Sstevel@tonic-gate rl_iter_f *cb, void *client_data, uint_t *abort_iter) 5567c478bd9Sstevel@tonic-gate { 5577c478bd9Sstevel@tonic-gate while (lmaddr) { 5587c478bd9Sstevel@tonic-gate Rt_map rmap; 5597c478bd9Sstevel@tonic-gate rd_loadobj_t lobj; 5607c478bd9Sstevel@tonic-gate int i; 5617c478bd9Sstevel@tonic-gate ulong_t off; 5627c478bd9Sstevel@tonic-gate Ehdr ehdr; 5637c478bd9Sstevel@tonic-gate Phdr phdr; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap, 5667c478bd9Sstevel@tonic-gate sizeof (Rt_map)) != PS_OK) { 5677c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 5687c478bd9Sstevel@tonic-gate return (RD_DBERR); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate * As of 'VERSION5' we only report objects 5737c478bd9Sstevel@tonic-gate * which have been fully relocated. While the maps 5747c478bd9Sstevel@tonic-gate * might be in a consistent state - if a object hasn't 5757c478bd9Sstevel@tonic-gate * been relocated - it's not really ready for the debuggers 5767c478bd9Sstevel@tonic-gate * to examine. This is mostly due to the fact that we 5777c478bd9Sstevel@tonic-gate * might still be mucking with the text-segment, if 5787c478bd9Sstevel@tonic-gate * we are - we could conflict with any break-points 5797c478bd9Sstevel@tonic-gate * the debuggers might have set. 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) { 5827c478bd9Sstevel@tonic-gate if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) { 5837c478bd9Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap); 5847c478bd9Sstevel@tonic-gate continue; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate lobj.rl_base = (psaddr_t)ADDR(&rmap); 5897c478bd9Sstevel@tonic-gate lobj.rl_flags = 0; 5907c478bd9Sstevel@tonic-gate lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap); 591*22872efbSedp if ((rap->rd_helper.rh_ops != NULL) && 592*22872efbSedp (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE)) 593*22872efbSedp lobj.rl_lmident = 594*22872efbSedp rap->rd_helper.rh_ops->rho_lmid; 5959acbbeafSnn else 5969acbbeafSnn lobj.rl_lmident = ident; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* 5997c478bd9Sstevel@tonic-gate * refnameaddr is only valid from a core file 6007c478bd9Sstevel@tonic-gate * which is VERSION3 or greater. 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) { 6037c478bd9Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)NAME(&rmap); 6047c478bd9Sstevel@tonic-gate lobj.rl_bend = 0; 6057c478bd9Sstevel@tonic-gate lobj.rl_padstart = 0; 6067c478bd9Sstevel@tonic-gate lobj.rl_padend = 0; 6077c478bd9Sstevel@tonic-gate } else { 6087c478bd9Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap); 6097c478bd9Sstevel@tonic-gate lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap); 6107c478bd9Sstevel@tonic-gate lobj.rl_padstart = PADSTART(&rmap); 6117c478bd9Sstevel@tonic-gate lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2) 6167c478bd9Sstevel@tonic-gate if (FLAGS(&rmap) & FLG_RT_IMGALLOC) 6177c478bd9Sstevel@tonic-gate lobj.rl_flags |= RD_FLG_MEM_OBJECT; 6187c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2) { 6197c478bd9Sstevel@tonic-gate lobj.rl_dynamic = (psaddr_t)DYN(&rmap); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION4) 6237c478bd9Sstevel@tonic-gate lobj.rl_tlsmodid = TLSMODID(&rmap); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate * Look for beginning of data segment. 6277c478bd9Sstevel@tonic-gate * 6287c478bd9Sstevel@tonic-gate * NOTE: the data segment can only be found for full 6297c478bd9Sstevel@tonic-gate * processes and not from core images. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate lobj.rl_data_base = 0; 6327c478bd9Sstevel@tonic-gate if (rap->rd_flags & RDF_FL_COREFILE) 6337c478bd9Sstevel@tonic-gate lobj.rl_data_base = 0; 6347c478bd9Sstevel@tonic-gate else { 6357c478bd9Sstevel@tonic-gate off = ADDR(&rmap); 6367c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&ehdr, 6377c478bd9Sstevel@tonic-gate sizeof (Ehdr)) != PS_OK) { 6387c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 6397c478bd9Sstevel@tonic-gate return (RD_DBERR); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate off += sizeof (Ehdr); 6427c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr.e_phnum; i++) { 6437c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&phdr, 6447c478bd9Sstevel@tonic-gate sizeof (Phdr)) != PS_OK) { 6457c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG( 6467c478bd9Sstevel@tonic-gate MSG_DB_LKMAPFAIL))); 6477c478bd9Sstevel@tonic-gate return (RD_DBERR); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate if ((phdr.p_type == PT_LOAD) && 6507c478bd9Sstevel@tonic-gate (phdr.p_flags & PF_W)) { 6517c478bd9Sstevel@tonic-gate lobj.rl_data_base = phdr.p_vaddr; 6527c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_DYN) 6537c478bd9Sstevel@tonic-gate lobj.rl_data_base += 6549acbbeafSnn ADDR(&rmap); 6557c478bd9Sstevel@tonic-gate break; 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate off += ehdr.e_phentsize; 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * When we transfer control to the client we free the 6637c478bd9Sstevel@tonic-gate * lock and re-atain it after we've returned from the 6647c478bd9Sstevel@tonic-gate * client. This is to avoid any deadlock situations. 6657c478bd9Sstevel@tonic-gate */ 6667c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data, 6679acbbeafSnn EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident))); 6687c478bd9Sstevel@tonic-gate RDAGUNLOCK(rap); 6697c478bd9Sstevel@tonic-gate if ((*cb)(&lobj, client_data) == 0) { 6707c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0))); 6717c478bd9Sstevel@tonic-gate RDAGLOCK(rap); 6727c478bd9Sstevel@tonic-gate *abort_iter = 1; 6737c478bd9Sstevel@tonic-gate break; 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate RDAGLOCK(rap); 6767c478bd9Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate return (RD_OK); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate rd_err_e 6837c478bd9Sstevel@tonic-gate _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 6867c478bd9Sstevel@tonic-gate TList list; 6877c478bd9Sstevel@tonic-gate TListnode lnode; 6887c478bd9Sstevel@tonic-gate Addr lnp; 6897c478bd9Sstevel@tonic-gate unsigned long ident; 6907c478bd9Sstevel@tonic-gate rd_err_e rc; 6917c478bd9Sstevel@tonic-gate uint_t abort_iter = 0; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 6949acbbeafSnn client_data)); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 6977c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 6987c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 6997c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 7007c478bd9Sstevel@tonic-gate return (RD_DBERR); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (db_priv.rtd_dynlmlst == 0) { 7047c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 7059acbbeafSnn EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 7067c478bd9Sstevel@tonic-gate return (RD_NOMAPS); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&list, 7107c478bd9Sstevel@tonic-gate sizeof (TList)) != PS_OK) { 7117c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 7129acbbeafSnn EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 7137c478bd9Sstevel@tonic-gate return (RD_DBERR); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate if (list.head == 0) { 7177c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 7189acbbeafSnn EC_ADDR((uintptr_t)list.head))); 7197c478bd9Sstevel@tonic-gate return (RD_NOMAPS); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (cb == 0) { 7247c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 7257c478bd9Sstevel@tonic-gate return (RD_ERR); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) { 7297c478bd9Sstevel@tonic-gate Lm_list lml; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * Iterate through the List of Lm_list's. 7337c478bd9Sstevel@tonic-gate */ 7347c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode, 7357c478bd9Sstevel@tonic-gate sizeof (TListnode)) != PS_OK) { 7367c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 7379acbbeafSnn EC_ADDR(lnp))); 7387c478bd9Sstevel@tonic-gate return (RD_DBERR); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data, (char *)&lml, 7427c478bd9Sstevel@tonic-gate sizeof (Lm_list)) != PS_OK) { 7437c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 7449acbbeafSnn EC_ADDR((uintptr_t)lnode.data))); 7457c478bd9Sstevel@tonic-gate return (RD_DBERR); 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate /* 7497c478bd9Sstevel@tonic-gate * Determine IDENT of current LM_LIST 7507c478bd9Sstevel@tonic-gate */ 7517c478bd9Sstevel@tonic-gate if (lml.lm_flags & LML_FLG_BASELM) 7527c478bd9Sstevel@tonic-gate ident = LM_ID_BASE; 7537c478bd9Sstevel@tonic-gate else if (lml.lm_flags & LML_FLG_RTLDLM) 7547c478bd9Sstevel@tonic-gate ident = LM_ID_LDSO; 7557c478bd9Sstevel@tonic-gate else 7567c478bd9Sstevel@tonic-gate ident = (unsigned long)lnode.data; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head, 7597c478bd9Sstevel@tonic-gate cb, client_data, &abort_iter)) != RD_OK) { 7607c478bd9Sstevel@tonic-gate return (rc); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate if (abort_iter) 7637c478bd9Sstevel@tonic-gate break; 7647c478bd9Sstevel@tonic-gate } 7659acbbeafSnn 7669acbbeafSnn if (rc != RD_OK) 7679acbbeafSnn return (rc); 7689acbbeafSnn 7699acbbeafSnn if (rap->rd_helper.rh_ops != NULL) 770*22872efbSedp return (rap->rd_helper.rh_ops->rho_loadobj_iter( 771*22872efbSedp rap->rd_helper.rh_data, cb, client_data)); 7729acbbeafSnn 7739acbbeafSnn return (RD_OK); 7747c478bd9Sstevel@tonic-gate } 775