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 /* 225240bea1SRod Evans * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdlib.h> 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <proc_service.h> 297c478bd9Sstevel@tonic-gate #include <link.h> 307c478bd9Sstevel@tonic-gate #include <rtld_db.h> 317c478bd9Sstevel@tonic-gate #include <rtld.h> 32*57ef7aa9SRod Evans #include <alist.h> 337c478bd9Sstevel@tonic-gate #include <_rtld_db.h> 347c478bd9Sstevel@tonic-gate #include <msg.h> 359acbbeafSnn #include <limits.h> 369acbbeafSnn #include <string.h> 379acbbeafSnn #include <sys/param.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * 64-bit builds are going to compile this module twice, the 417c478bd9Sstevel@tonic-gate * second time with _ELF64 defined. These defines should make 427c478bd9Sstevel@tonic-gate * all the necessary adjustments to the code. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate #ifdef _LP64 457c478bd9Sstevel@tonic-gate #ifdef _ELF64 467c478bd9Sstevel@tonic-gate #define _rd_event_enable32 _rd_event_enable64 477c478bd9Sstevel@tonic-gate #define _rd_event_getmsg32 _rd_event_getmsg64 4822872efbSedp #define _rd_get_dyns32 _rd_get_dyns64 4922872efbSedp #define _rd_get_ehdr32 _rd_get_ehdr64 507c478bd9Sstevel@tonic-gate #define _rd_objpad_enable32 _rd_objpad_enable64 517c478bd9Sstevel@tonic-gate #define _rd_loadobj_iter32 _rd_loadobj_iter64 5222872efbSedp #define _rd_reset32 _rd_reset64 537c478bd9Sstevel@tonic-gate #define find_dynamic_ent32 find_dynamic_ent64 5422872efbSedp #define validate_rdebug32 validate_rdebug64 55*57ef7aa9SRod Evans #define TAPlist APlist 56*57ef7aa9SRod Evans #define TLm_list Lm_list 57adbfe822Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_64 587c478bd9Sstevel@tonic-gate #else /* ELF32 */ 597c478bd9Sstevel@tonic-gate #define Rt_map Rt_map32 607c478bd9Sstevel@tonic-gate #define Rtld_db_priv Rtld_db_priv32 61*57ef7aa9SRod Evans #define TAPlist APlist32 62*57ef7aa9SRod Evans #define TLm_list Lm_list32 63adbfe822Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32 647c478bd9Sstevel@tonic-gate #endif /* _ELF64 */ 657c478bd9Sstevel@tonic-gate #else /* _LP64 */ 66*57ef7aa9SRod Evans #define TAPlist APlist 67*57ef7aa9SRod Evans #define TLm_list Lm_list 68adbfe822Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32 697c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 707c478bd9Sstevel@tonic-gate 715eae5a6fSedp /* 725eae5a6fSedp * BrandZ added ps_pbrandname(). Many debuggers that link directly 735eae5a6fSedp * against librtld_db.so may not implement this interface. Hence 745eae5a6fSedp * we won't call the function directly, instead we'll try to look it 755eae5a6fSedp * up using the linker first and only invoke it if we find it. 765eae5a6fSedp */ 775eae5a6fSedp typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *, 785eae5a6fSedp char *, size_t); 795eae5a6fSedp 8022872efbSedp rd_err_e 8122872efbSedp validate_rdebug32(struct rd_agent *rap) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 847c478bd9Sstevel@tonic-gate psaddr_t db_privp; 857c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if (rap->rd_rdebug == 0) 887c478bd9Sstevel@tonic-gate return (RD_ERR); 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * The rtld_db_priv structure contains both the traditional (exposed) 917c478bd9Sstevel@tonic-gate * r_debug structure as well as private data only available to 927c478bd9Sstevel@tonic-gate * this library. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate db_privp = rap->rd_rdebug; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * Verify that librtld_db & rtld are at the proper revision 987c478bd9Sstevel@tonic-gate * levels. 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate if (ps_pread(php, db_privp, (char *)&db_priv, 1017c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 1027c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1), 1039acbbeafSnn EC_ADDR(db_privp))); 1047c478bd9Sstevel@tonic-gate return (RD_DBERR); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate if ((db_priv.rtd_version < R_RTLDDB_VERSION1) || 1087c478bd9Sstevel@tonic-gate (db_priv.rtd_version > R_RTLDDB_VERSION)) { 1097c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 1109acbbeafSnn db_priv.rtd_version, R_RTLDDB_VERSION)); 1117c478bd9Sstevel@tonic-gate return (RD_NOCAPAB); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * Is the image being examined from a core file or not. 1167c478bd9Sstevel@tonic-gate * If it is a core file then the following write will fail. 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate if (ps_pwrite(php, db_privp, (char *)&db_priv, 1197c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) 1207c478bd9Sstevel@tonic-gate rap->rd_flags |= RDF_FL_COREFILE; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * If this *is not* a core file then rtld_db & ld.so.1 are 1247c478bd9Sstevel@tonic-gate * considered tightly coupled. If the versions of our private 1257c478bd9Sstevel@tonic-gate * data structures don't match - fail! 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate if (((rap->rd_flags & RDF_FL_COREFILE) == 0) && 1287c478bd9Sstevel@tonic-gate (db_priv.rtd_version != R_RTLDDB_VERSION)) { 1297c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS), 1309acbbeafSnn db_priv.rtd_version, R_RTLDDB_VERSION)); 1317c478bd9Sstevel@tonic-gate return (RD_NOCAPAB); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate rap->rd_rdebugvers = db_priv.rtd_version; 1357c478bd9Sstevel@tonic-gate rap->rd_rtlddbpriv = db_privp; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug), 1389acbbeafSnn R_RTLDDB_VERSION, rap->rd_rdebugvers, 1399acbbeafSnn rap->rd_flags & RDF_FL_COREFILE)); 1407c478bd9Sstevel@tonic-gate return (RD_OK); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate rd_err_e 1457c478bd9Sstevel@tonic-gate find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr, 1467c478bd9Sstevel@tonic-gate Xword dyntag, Dyn *dyn) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 1497c478bd9Sstevel@tonic-gate Dyn d; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate d.d_tag = DT_NULL; 1527c478bd9Sstevel@tonic-gate do { 1537c478bd9Sstevel@tonic-gate if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) != 1547c478bd9Sstevel@tonic-gate PS_OK) { 1557c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4), 1569acbbeafSnn EC_ADDR(dynaddr))); 1577c478bd9Sstevel@tonic-gate return (RD_DBERR); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate dynaddr += sizeof (d); 1607c478bd9Sstevel@tonic-gate if (d.d_tag == dyntag) 1617c478bd9Sstevel@tonic-gate break; 1627c478bd9Sstevel@tonic-gate } while (d.d_tag != DT_NULL); 1637c478bd9Sstevel@tonic-gate if (d.d_tag == dyntag) { 1647c478bd9Sstevel@tonic-gate *dyn = d; 1657c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag), 1667c478bd9Sstevel@tonic-gate EC_ADDR(d.d_un.d_val))); 1677c478bd9Sstevel@tonic-gate return (RD_OK); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag))); 1707c478bd9Sstevel@tonic-gate return (RD_DBERR); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1739acbbeafSnn extern char rtld_db_helper_path[MAXPATHLEN]; 1749acbbeafSnn 1757c478bd9Sstevel@tonic-gate rd_err_e 1767c478bd9Sstevel@tonic-gate _rd_reset32(struct rd_agent *rap) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate psaddr_t symaddr; 1797c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 1807c478bd9Sstevel@tonic-gate const auxv_t *auxvp = NULL; 1817c478bd9Sstevel@tonic-gate rd_err_e rc = RD_OK; 1829acbbeafSnn char brandname[MAXPATHLEN]; 1839acbbeafSnn char brandlib[MAXPATHLEN]; 1845eae5a6fSedp ps_pbrandname_fp_t ps_pbrandname; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * librtld_db attempts three different methods to find 1887c478bd9Sstevel@tonic-gate * the r_debug structure which is required to 1897c478bd9Sstevel@tonic-gate * initialize itself. The methods are: 1907c478bd9Sstevel@tonic-gate * method1: 1917c478bd9Sstevel@tonic-gate * entirely independent of any text segment 1927c478bd9Sstevel@tonic-gate * and relies on the AT_SUN_LDDATA auxvector 1937c478bd9Sstevel@tonic-gate * to find the ld.so.1::rdebug structure. 1947c478bd9Sstevel@tonic-gate * method2: 1957c478bd9Sstevel@tonic-gate * lookup symbols in ld.so.1's symbol table 1967c478bd9Sstevel@tonic-gate * to find the r_debug symbol. 1977c478bd9Sstevel@tonic-gate * method3: 1987c478bd9Sstevel@tonic-gate * (old dbx method) dependent upon the 1997c478bd9Sstevel@tonic-gate * text segment/symbol table of the 2007c478bd9Sstevel@tonic-gate * executable and not ld.so.1. We lookup the 2017c478bd9Sstevel@tonic-gate * _DYNAMIC symbol in the executable and look for 2027c478bd9Sstevel@tonic-gate * the DT_DEBUG entry in the .dynamic table. This 2037c478bd9Sstevel@tonic-gate * points to rdebug. 2047c478bd9Sstevel@tonic-gate * 2057c478bd9Sstevel@tonic-gate * If none of that works - we fail. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel)); 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Method1 2107c478bd9Sstevel@tonic-gate * 2117c478bd9Sstevel@tonic-gate * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA 2127c478bd9Sstevel@tonic-gate */ 2139acbbeafSnn 2147c478bd9Sstevel@tonic-gate if (ps_pauxv(php, &auxvp) != PS_OK) { 2157c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV))); 2167c478bd9Sstevel@tonic-gate rc = RD_ERR; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate rap->rd_rdebug = 0; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (auxvp != NULL) { 2227c478bd9Sstevel@tonic-gate rc = RD_ERR; 2237c478bd9Sstevel@tonic-gate while (auxvp->a_type != AT_NULL) { 2247c478bd9Sstevel@tonic-gate if (auxvp->a_type == AT_SUN_LDDATA) { 2257c478bd9Sstevel@tonic-gate /* LINTED */ 2267c478bd9Sstevel@tonic-gate rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr; 2277c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA), 2287c478bd9Sstevel@tonic-gate rap->rd_rdebug)); 22922872efbSedp rc = validate_rdebug32(rap); 2307c478bd9Sstevel@tonic-gate break; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate auxvp++; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * method2 - look for r_rdebug symbol in ld.so.1 2387c478bd9Sstevel@tonic-gate */ 2397c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * If the AT_SUN_LDDATA auxv vector is not present 2427c478bd9Sstevel@tonic-gate * fall back on doing a symlookup of 2437c478bd9Sstevel@tonic-gate * the r_debug symbol. This is for backward 2447c478bd9Sstevel@tonic-gate * compatiblity with older OS's 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA))); 2477c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG), 2487c478bd9Sstevel@tonic-gate &symaddr) != PS_OK) { 2497c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL), 2509acbbeafSnn MSG_ORIG(MSG_SYM_DEBUG))); 2517c478bd9Sstevel@tonic-gate rc = RD_DBERR; 2527c478bd9Sstevel@tonic-gate } else { 2537c478bd9Sstevel@tonic-gate rap->rd_rdebug = symaddr; 2547c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG), 2559acbbeafSnn EC_ADDR(symaddr))); 25622872efbSedp rc = validate_rdebug32(rap); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * method3 - find DT_DEBUG in the executables .dynamic section. 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2657c478bd9Sstevel@tonic-gate Dyn dyn; 2667c478bd9Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_EXEC, 2677c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) { 2687c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC))); 2697c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2707c478bd9Sstevel@tonic-gate return (rc); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn); 2737c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2747c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2757c478bd9Sstevel@tonic-gate return (rc); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate rap->rd_rdebug = dyn.d_un.d_ptr; 27822872efbSedp rc = validate_rdebug32(rap); 2797c478bd9Sstevel@tonic-gate if (rc != RD_OK) { 2807c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED))); 2817c478bd9Sstevel@tonic-gate return (rc); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2859acbbeafSnn /* 28622872efbSedp * If we are debugging a branded executable, load the appropriate 28722872efbSedp * helper library, and call its initialization routine. Being unable 28822872efbSedp * to load the helper library is not a critical error. (Hopefully 28922872efbSedp * we'll still be able to access some objects in the target.) 2909acbbeafSnn */ 2915eae5a6fSedp ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname"); 29222872efbSedp while ((ps_pbrandname != NULL) && 2935eae5a6fSedp (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) { 2949acbbeafSnn const char *isa = ""; 2959acbbeafSnn 29622872efbSedp #ifdef _LP64 2979acbbeafSnn isa = MSG_ORIG(MSG_DB_64BIT_PREFIX); 29822872efbSedp #endif /* _LP64 */ 2999acbbeafSnn 3009acbbeafSnn if (rtld_db_helper_path[0] != '\0') 3019acbbeafSnn (void) snprintf(brandlib, MAXPATHLEN, 3029acbbeafSnn MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX), 3039acbbeafSnn rtld_db_helper_path, 3049acbbeafSnn MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 3059acbbeafSnn brandname); 3069acbbeafSnn else 3079acbbeafSnn (void) snprintf(brandlib, MAXPATHLEN, 3089acbbeafSnn MSG_ORIG(MSG_DB_BRAND_HELPERPATH), 3099acbbeafSnn MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa, 3109acbbeafSnn brandname); 3119acbbeafSnn 31222872efbSedp rap->rd_helper.rh_dlhandle = dlopen(brandlib, 31322872efbSedp RTLD_LAZY | RTLD_LOCAL); 31422872efbSedp if (rap->rd_helper.rh_dlhandle == NULL) { 3159acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED), 3169acbbeafSnn brandlib)); 31722872efbSedp break; 3189acbbeafSnn } 3199acbbeafSnn 32022872efbSedp rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle, 32122872efbSedp MSG_ORIG(MSG_SYM_BRANDOPS)); 32222872efbSedp if (rap->rd_helper.rh_ops == NULL) { 3239acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS), 3249acbbeafSnn brandlib)); 32522872efbSedp (void) dlclose(rap->rd_helper.rh_dlhandle); 32622872efbSedp rap->rd_helper.rh_dlhandle = NULL; 32722872efbSedp break; 3289acbbeafSnn } 3299acbbeafSnn 33022872efbSedp rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap, 33122872efbSedp php); 3329acbbeafSnn if (rap->rd_helper.rh_data == NULL) { 3339acbbeafSnn LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED))); 3349acbbeafSnn (void) dlclose(rap->rd_helper.rh_dlhandle); 3359acbbeafSnn rap->rd_helper.rh_dlhandle = NULL; 3369acbbeafSnn rap->rd_helper.rh_ops = NULL; 33722872efbSedp break; 33822872efbSedp } 33922872efbSedp 34022872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname)); 34122872efbSedp break; 342adbfe822Srie 343adbfe822Srie /* NOTREACHED */ 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 37622872efbSedp rd_err_e 37722872efbSedp _rd_get_ehdr32(struct rd_agent *rap, 37822872efbSedp psaddr_t addr, Ehdr *ehdr, uint_t *phnum) 37922872efbSedp { 38022872efbSedp struct ps_prochandle *php = rap->rd_psp; 38122872efbSedp Shdr shdr; 38222872efbSedp 38322872efbSedp if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) { 38422872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 38522872efbSedp return (RD_ERR); 38622872efbSedp } 38722872efbSedp if (phnum == NULL) 38822872efbSedp return (RD_OK); 38922872efbSedp 39022872efbSedp if (ehdr->e_phnum != PN_XNUM) { 39122872efbSedp *phnum = ehdr->e_phnum; 39222872efbSedp return (RD_OK); 39322872efbSedp } 39422872efbSedp 39522872efbSedp /* deal with elf extended program headers */ 39622872efbSedp if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr))) 39722872efbSedp return (RD_ERR); 39822872efbSedp 39922872efbSedp addr += ehdr->e_shoff; 40022872efbSedp if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) { 40122872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr))); 40222872efbSedp return (RD_ERR); 40322872efbSedp } 40422872efbSedp 40522872efbSedp if (shdr.sh_info == 0) 40622872efbSedp return (RD_ERR); 40722872efbSedp 40822872efbSedp *phnum = shdr.sh_info; 40922872efbSedp return (RD_OK); 41022872efbSedp } 41122872efbSedp 41222872efbSedp rd_err_e 41322872efbSedp _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz) 41422872efbSedp { 41522872efbSedp struct ps_prochandle *php = rap->rd_psp; 41622872efbSedp rd_err_e err; 41722872efbSedp uint_t phnum; 41822872efbSedp Ehdr ehdr; 41922872efbSedp Phdr phdr; 42022872efbSedp Dyn *dynp; 42122872efbSedp int i; 42222872efbSedp 42322872efbSedp /* We only need to muck with dyn elements for ET_DYN objects */ 42422872efbSedp if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK) 42522872efbSedp return (err); 42622872efbSedp 42722872efbSedp for (i = 0; i < phnum; i++) { 42822872efbSedp psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize); 42922872efbSedp if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) { 43022872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a))); 43122872efbSedp return (RD_ERR); 43222872efbSedp } 43322872efbSedp if (phdr.p_type == PT_DYNAMIC) 43422872efbSedp break; 43522872efbSedp } 43622872efbSedp if (i == phnum) 43722872efbSedp return (RD_ERR); 43822872efbSedp 43922872efbSedp if ((dynp = malloc(phdr.p_filesz)) == NULL) 44022872efbSedp return (RD_ERR); 44122872efbSedp if (ehdr.e_type == ET_DYN) 44222872efbSedp phdr.p_vaddr += addr; 44322872efbSedp if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) { 44422872efbSedp free(dynp); 44522872efbSedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), 44622872efbSedp EC_ADDR(phdr.p_vaddr))); 44722872efbSedp return (RD_ERR); 44822872efbSedp } 44922872efbSedp 45022872efbSedp *dynpp = dynp; 451544fa60cSedp if (dynpp_sz != NULL) 452544fa60cSedp *dynpp_sz = phdr.p_filesz; 45322872efbSedp return (RD_OK); 45422872efbSedp } 45522872efbSedp 4567c478bd9Sstevel@tonic-gate rd_err_e 4577c478bd9Sstevel@tonic-gate _rd_event_enable32(rd_agent_t *rap, int onoff) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 4607c478bd9Sstevel@tonic-gate Rtld_db_priv rdb; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff)); 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * Tell the debugged process that debugging is occuring 4657c478bd9Sstevel@tonic-gate * This will enable the storing of event messages so that 4667c478bd9Sstevel@tonic-gate * the can be gathered by the debugger. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate if (ps_pread(php, rap->rd_rdebug, (char *)&rdb, 4697c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4707c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1), 4717c478bd9Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb))); 4727c478bd9Sstevel@tonic-gate return (RD_DBERR); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (onoff) 4767c478bd9Sstevel@tonic-gate rdb.rtd_rdebug.r_flags |= RD_FL_DBG; 4777c478bd9Sstevel@tonic-gate else 4787c478bd9Sstevel@tonic-gate rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb, 4817c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4827c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1), 4837c478bd9Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb))); 4847c478bd9Sstevel@tonic-gate return (RD_DBERR); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate return (RD_OK); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate rd_err_e 4927c478bd9Sstevel@tonic-gate _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate Rtld_db_priv rdb; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb, 4977c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 4987c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2), 4997c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rdebug))); 5007c478bd9Sstevel@tonic-gate return (RD_DBERR); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate emsg->type = rdb.rtd_rdebug.r_rdevent; 5037c478bd9Sstevel@tonic-gate if (emsg->type == RD_DLACTIVITY) { 5047c478bd9Sstevel@tonic-gate switch (rdb.rtd_rdebug.r_state) { 5057c478bd9Sstevel@tonic-gate case RT_CONSISTENT: 5067c478bd9Sstevel@tonic-gate emsg->u.state = RD_CONSISTENT; 5077c478bd9Sstevel@tonic-gate break; 5087c478bd9Sstevel@tonic-gate case RT_ADD: 5097c478bd9Sstevel@tonic-gate emsg->u.state = RD_ADD; 5107c478bd9Sstevel@tonic-gate break; 5117c478bd9Sstevel@tonic-gate case RT_DELETE: 5127c478bd9Sstevel@tonic-gate emsg->u.state = RD_DELETE; 5137c478bd9Sstevel@tonic-gate break; 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate } else 5167c478bd9Sstevel@tonic-gate emsg->u.state = RD_NOSTATE; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel, 5199acbbeafSnn emsg->type, emsg->u.state)); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate return (RD_OK); 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate rd_err_e 5267c478bd9Sstevel@tonic-gate _rd_objpad_enable32(struct rd_agent *rap, size_t padsize) 5277c478bd9Sstevel@tonic-gate { 5287c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 5297c478bd9Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize))); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv, 5347c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 5357c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3), 5367c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 5377c478bd9Sstevel@tonic-gate return (RD_DBERR); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate #if defined(_LP64) && !defined(_ELF64) 5407c478bd9Sstevel@tonic-gate /*LINTED*/ 5417c478bd9Sstevel@tonic-gate db_priv.rtd_objpad = (uint32_t)padsize; 5427c478bd9Sstevel@tonic-gate #else 5437c478bd9Sstevel@tonic-gate db_priv.rtd_objpad = padsize; 5447c478bd9Sstevel@tonic-gate #endif 5457c478bd9Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv, 5467c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 5477c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2), 5487c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 5497c478bd9Sstevel@tonic-gate return (RD_DBERR); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate return (RD_OK); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate static rd_err_e 5557c478bd9Sstevel@tonic-gate iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr, 5560ef25df5SEdward Pilatowicz rl_iter_f *cb, void *client_data, uint_t *abort_iterp) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate while (lmaddr) { 5597c478bd9Sstevel@tonic-gate Rt_map rmap; 5607c478bd9Sstevel@tonic-gate rd_loadobj_t lobj; 5617c478bd9Sstevel@tonic-gate int i; 5627c478bd9Sstevel@tonic-gate ulong_t off; 5637c478bd9Sstevel@tonic-gate Ehdr ehdr; 5647c478bd9Sstevel@tonic-gate Phdr phdr; 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap, 5677c478bd9Sstevel@tonic-gate sizeof (Rt_map)) != PS_OK) { 5687c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 5697c478bd9Sstevel@tonic-gate return (RD_DBERR); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * As of 'VERSION5' we only report objects 5747c478bd9Sstevel@tonic-gate * which have been fully relocated. While the maps 5757c478bd9Sstevel@tonic-gate * might be in a consistent state - if a object hasn't 5767c478bd9Sstevel@tonic-gate * been relocated - it's not really ready for the debuggers 5777c478bd9Sstevel@tonic-gate * to examine. This is mostly due to the fact that we 5787c478bd9Sstevel@tonic-gate * might still be mucking with the text-segment, if 5797c478bd9Sstevel@tonic-gate * we are - we could conflict with any break-points 5807c478bd9Sstevel@tonic-gate * the debuggers might have set. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) { 5837c478bd9Sstevel@tonic-gate if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) { 5847c478bd9Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap); 5857c478bd9Sstevel@tonic-gate continue; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate lobj.rl_base = (psaddr_t)ADDR(&rmap); 5907c478bd9Sstevel@tonic-gate lobj.rl_flags = 0; 5917c478bd9Sstevel@tonic-gate lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap); 59222872efbSedp if ((rap->rd_helper.rh_ops != NULL) && 59322872efbSedp (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE)) 59422872efbSedp lobj.rl_lmident = 59522872efbSedp rap->rd_helper.rh_ops->rho_lmid; 5969acbbeafSnn else 5979acbbeafSnn lobj.rl_lmident = ident; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * refnameaddr is only valid from a core file 6017c478bd9Sstevel@tonic-gate * which is VERSION3 or greater. 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) { 6047c478bd9Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)NAME(&rmap); 6057c478bd9Sstevel@tonic-gate lobj.rl_bend = 0; 6067c478bd9Sstevel@tonic-gate lobj.rl_padstart = 0; 6077c478bd9Sstevel@tonic-gate lobj.rl_padend = 0; 6087c478bd9Sstevel@tonic-gate } else { 6097c478bd9Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap); 6107c478bd9Sstevel@tonic-gate lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap); 6117c478bd9Sstevel@tonic-gate lobj.rl_padstart = PADSTART(&rmap); 6127c478bd9Sstevel@tonic-gate lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2) 6177c478bd9Sstevel@tonic-gate if (FLAGS(&rmap) & FLG_RT_IMGALLOC) 6187c478bd9Sstevel@tonic-gate lobj.rl_flags |= RD_FLG_MEM_OBJECT; 6197c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2) { 6207c478bd9Sstevel@tonic-gate lobj.rl_dynamic = (psaddr_t)DYN(&rmap); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION4) 6247c478bd9Sstevel@tonic-gate lobj.rl_tlsmodid = TLSMODID(&rmap); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* 6277c478bd9Sstevel@tonic-gate * Look for beginning of data segment. 6287c478bd9Sstevel@tonic-gate * 6297c478bd9Sstevel@tonic-gate * NOTE: the data segment can only be found for full 6307c478bd9Sstevel@tonic-gate * processes and not from core images. 6317c478bd9Sstevel@tonic-gate */ 6327c478bd9Sstevel@tonic-gate lobj.rl_data_base = 0; 6337c478bd9Sstevel@tonic-gate if (rap->rd_flags & RDF_FL_COREFILE) 6347c478bd9Sstevel@tonic-gate lobj.rl_data_base = 0; 6357c478bd9Sstevel@tonic-gate else { 6367c478bd9Sstevel@tonic-gate off = ADDR(&rmap); 6377c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&ehdr, 6387c478bd9Sstevel@tonic-gate sizeof (Ehdr)) != PS_OK) { 6397c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL))); 6407c478bd9Sstevel@tonic-gate return (RD_DBERR); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate off += sizeof (Ehdr); 6437c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr.e_phnum; i++) { 6447c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&phdr, 6457c478bd9Sstevel@tonic-gate sizeof (Phdr)) != PS_OK) { 6467c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG( 6477c478bd9Sstevel@tonic-gate MSG_DB_LKMAPFAIL))); 6487c478bd9Sstevel@tonic-gate return (RD_DBERR); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate if ((phdr.p_type == PT_LOAD) && 6517c478bd9Sstevel@tonic-gate (phdr.p_flags & PF_W)) { 6527c478bd9Sstevel@tonic-gate lobj.rl_data_base = phdr.p_vaddr; 6537c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_DYN) 6547c478bd9Sstevel@tonic-gate lobj.rl_data_base += 6559acbbeafSnn ADDR(&rmap); 6567c478bd9Sstevel@tonic-gate break; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate off += ehdr.e_phentsize; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * When we transfer control to the client we free the 6647c478bd9Sstevel@tonic-gate * lock and re-atain it after we've returned from the 6657c478bd9Sstevel@tonic-gate * client. This is to avoid any deadlock situations. 6667c478bd9Sstevel@tonic-gate */ 6677c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data, 6689acbbeafSnn EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident))); 6697c478bd9Sstevel@tonic-gate RDAGUNLOCK(rap); 6707c478bd9Sstevel@tonic-gate if ((*cb)(&lobj, client_data) == 0) { 6717c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0))); 6727c478bd9Sstevel@tonic-gate RDAGLOCK(rap); 6730ef25df5SEdward Pilatowicz *abort_iterp = 1; 6747c478bd9Sstevel@tonic-gate break; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate RDAGLOCK(rap); 6777c478bd9Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate return (RD_OK); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate 6830ef25df5SEdward Pilatowicz static rd_err_e 6840ef25df5SEdward Pilatowicz _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data, 6850ef25df5SEdward Pilatowicz uint_t *abort_iterp) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate Rtld_db_priv db_priv; 688*57ef7aa9SRod Evans TAPlist apl; 689*57ef7aa9SRod Evans uintptr_t datap, nitems; 690*57ef7aa9SRod Evans Addr addr; 6917c478bd9Sstevel@tonic-gate rd_err_e rc; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb, 6949acbbeafSnn client_data)); 6957c478bd9Sstevel@tonic-gate 696*57ef7aa9SRod Evans if (cb == NULL) { 697*57ef7aa9SRod Evans LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER))); 698*57ef7aa9SRod Evans return (RD_ERR); 699*57ef7aa9SRod Evans } 700*57ef7aa9SRod Evans 7017c478bd9Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv, 7027c478bd9Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) { 7037c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1), 7047c478bd9Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv))); 7057c478bd9Sstevel@tonic-gate return (RD_DBERR); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 708*57ef7aa9SRod Evans if (db_priv.rtd_dynlmlst == NULL) { 7097c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT), 7109acbbeafSnn EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 7117c478bd9Sstevel@tonic-gate return (RD_NOMAPS); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 714*57ef7aa9SRod Evans if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr, 715*57ef7aa9SRod Evans sizeof (Addr)) != PS_OK) { 7167c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3), 7179acbbeafSnn EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 7187c478bd9Sstevel@tonic-gate return (RD_DBERR); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 721*57ef7aa9SRod Evans if (addr == NULL) { 7227c478bd9Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1), 723*57ef7aa9SRod Evans EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst))); 7247c478bd9Sstevel@tonic-gate return (RD_NOMAPS); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 727*57ef7aa9SRod Evans if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl, 728*57ef7aa9SRod Evans sizeof (TAPlist)) != PS_OK) { 729*57ef7aa9SRod Evans LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4), 730*57ef7aa9SRod Evans EC_ADDR((uintptr_t)addr))); 731*57ef7aa9SRod Evans return (RD_DBERR); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 734*57ef7aa9SRod Evans /* 735*57ef7aa9SRod Evans * Iterate through each apl.ap_data[] entry. 736*57ef7aa9SRod Evans */ 737*57ef7aa9SRod Evans for (datap = (uintptr_t)((char *)(uintptr_t)addr + 738*57ef7aa9SRod Evans ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0; 739*57ef7aa9SRod Evans nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) { 740*57ef7aa9SRod Evans TLm_list lm; 741*57ef7aa9SRod Evans ulong_t ident; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* 744*57ef7aa9SRod Evans * Obtain the Lm_list address for this apl.ap_data[] entry. 7457c478bd9Sstevel@tonic-gate */ 746*57ef7aa9SRod Evans if (ps_pread(rap->rd_psp, (psaddr_t)datap, (char *)&addr, 747*57ef7aa9SRod Evans sizeof (Addr)) != PS_OK) { 748*57ef7aa9SRod Evans LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5), 749*57ef7aa9SRod Evans EC_ADDR(datap))); 7507c478bd9Sstevel@tonic-gate return (RD_DBERR); 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate 753*57ef7aa9SRod Evans /* 754*57ef7aa9SRod Evans * Obtain the Lm_list data for this Lm_list address. 755*57ef7aa9SRod Evans */ 756*57ef7aa9SRod Evans if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm, 757*57ef7aa9SRod Evans sizeof (TLm_list)) != PS_OK) { 758*57ef7aa9SRod Evans LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6), 759*57ef7aa9SRod Evans EC_ADDR((uintptr_t)addr))); 7607c478bd9Sstevel@tonic-gate return (RD_DBERR); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * Determine IDENT of current LM_LIST 7657c478bd9Sstevel@tonic-gate */ 766*57ef7aa9SRod Evans if (lm.lm_flags & LML_FLG_BASELM) 7677c478bd9Sstevel@tonic-gate ident = LM_ID_BASE; 768*57ef7aa9SRod Evans else if (lm.lm_flags & LML_FLG_RTLDLM) 7697c478bd9Sstevel@tonic-gate ident = LM_ID_LDSO; 7707c478bd9Sstevel@tonic-gate else 771*57ef7aa9SRod Evans ident = (ulong_t)addr; 7727c478bd9Sstevel@tonic-gate 773*57ef7aa9SRod Evans if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head, 7740ef25df5SEdward Pilatowicz cb, client_data, abort_iterp)) != RD_OK) { 7757c478bd9Sstevel@tonic-gate return (rc); 7767c478bd9Sstevel@tonic-gate } 7770ef25df5SEdward Pilatowicz if (*abort_iterp != 0) 7787c478bd9Sstevel@tonic-gate break; 7797c478bd9Sstevel@tonic-gate } 7809acbbeafSnn 7810ef25df5SEdward Pilatowicz return (rc); 7820ef25df5SEdward Pilatowicz } 7830ef25df5SEdward Pilatowicz 7840ef25df5SEdward Pilatowicz rd_err_e 7850ef25df5SEdward Pilatowicz _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data) 7860ef25df5SEdward Pilatowicz { 7875240bea1SRod Evans rd_err_e rc, rc_brand = RD_OK; 7880ef25df5SEdward Pilatowicz uint_t abort_iter = 0; 7890ef25df5SEdward Pilatowicz 7900ef25df5SEdward Pilatowicz /* First iterate over the native target objects */ 7910ef25df5SEdward Pilatowicz rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter); 7920ef25df5SEdward Pilatowicz if (abort_iter != 0) 7939acbbeafSnn return (rc); 7949acbbeafSnn 7950ef25df5SEdward Pilatowicz /* Then iterate over any branded objects. */ 7960ef25df5SEdward Pilatowicz if ((rap->rd_helper.rh_ops != NULL) && 7970ef25df5SEdward Pilatowicz (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL)) 7980ef25df5SEdward Pilatowicz rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter( 7990ef25df5SEdward Pilatowicz rap->rd_helper.rh_data, cb, client_data); 8009acbbeafSnn 8015240bea1SRod Evans rc = (rc != RD_OK) ? rc : rc_brand; 8020ef25df5SEdward Pilatowicz return (rc); 8037c478bd9Sstevel@tonic-gate } 804