10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52712Snn35248 * Common Development and Distribution License (the "License").
62712Snn35248 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11671SGerald.Jelinek@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdlib.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <proc_service.h>
290Sstevel@tonic-gate #include <link.h>
300Sstevel@tonic-gate #include <rtld_db.h>
310Sstevel@tonic-gate #include <rtld.h>
329131SRod.Evans@Sun.COM #include <alist.h>
3310167SRod.Evans@Sun.COM #include <list.h>
340Sstevel@tonic-gate #include <_rtld_db.h>
350Sstevel@tonic-gate #include <msg.h>
362712Snn35248 #include <limits.h>
372712Snn35248 #include <string.h>
382712Snn35248 #include <sys/param.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate * 64-bit builds are going to compile this module twice, the
420Sstevel@tonic-gate * second time with _ELF64 defined. These defines should make
430Sstevel@tonic-gate * all the necessary adjustments to the code.
440Sstevel@tonic-gate */
450Sstevel@tonic-gate #ifdef _LP64
460Sstevel@tonic-gate #ifdef _ELF64
470Sstevel@tonic-gate #define _rd_event_enable32 _rd_event_enable64
480Sstevel@tonic-gate #define _rd_event_getmsg32 _rd_event_getmsg64
496830Sedp #define _rd_get_dyns32 _rd_get_dyns64
506830Sedp #define _rd_get_ehdr32 _rd_get_ehdr64
510Sstevel@tonic-gate #define _rd_objpad_enable32 _rd_objpad_enable64
520Sstevel@tonic-gate #define _rd_loadobj_iter32 _rd_loadobj_iter64
536830Sedp #define _rd_reset32 _rd_reset64
540Sstevel@tonic-gate #define find_dynamic_ent32 find_dynamic_ent64
556830Sedp #define validate_rdebug32 validate_rdebug64
569131SRod.Evans@Sun.COM #define TAPlist APlist
579131SRod.Evans@Sun.COM #define TLm_list Lm_list
5810167SRod.Evans@Sun.COM #define TList List
5910167SRod.Evans@Sun.COM #define TListnode Listnode
606874Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_64
610Sstevel@tonic-gate #else /* ELF32 */
620Sstevel@tonic-gate #define Rt_map Rt_map32
630Sstevel@tonic-gate #define Rtld_db_priv Rtld_db_priv32
649131SRod.Evans@Sun.COM #define TAPlist APlist32
659131SRod.Evans@Sun.COM #define TLm_list Lm_list32
6610167SRod.Evans@Sun.COM #define TList List32
6710167SRod.Evans@Sun.COM #define TListnode Listnode32
6810167SRod.Evans@Sun.COM #define Lm_list Lm_list32
696874Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
700Sstevel@tonic-gate #endif /* _ELF64 */
710Sstevel@tonic-gate #else /* _LP64 */
729131SRod.Evans@Sun.COM #define TAPlist APlist
739131SRod.Evans@Sun.COM #define TLm_list Lm_list
7410167SRod.Evans@Sun.COM #define TList List
7510167SRod.Evans@Sun.COM #define TListnode Listnode
766874Srie #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
770Sstevel@tonic-gate #endif /* _LP64 */
780Sstevel@tonic-gate
795041Sedp /*
805041Sedp * BrandZ added ps_pbrandname(). Many debuggers that link directly
815041Sedp * against librtld_db.so may not implement this interface. Hence
825041Sedp * we won't call the function directly, instead we'll try to look it
835041Sedp * up using the linker first and only invoke it if we find it.
845041Sedp */
855041Sedp typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
865041Sedp char *, size_t);
875041Sedp
886830Sedp rd_err_e
validate_rdebug32(struct rd_agent * rap)896830Sedp validate_rdebug32(struct rd_agent *rap)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp;
920Sstevel@tonic-gate psaddr_t db_privp;
930Sstevel@tonic-gate Rtld_db_priv db_priv;
940Sstevel@tonic-gate
950Sstevel@tonic-gate if (rap->rd_rdebug == 0)
960Sstevel@tonic-gate return (RD_ERR);
9710167SRod.Evans@Sun.COM
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate * The rtld_db_priv structure contains both the traditional (exposed)
1000Sstevel@tonic-gate * r_debug structure as well as private data only available to
1010Sstevel@tonic-gate * this library.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate db_privp = rap->rd_rdebug;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate * Verify that librtld_db & rtld are at the proper revision
1070Sstevel@tonic-gate * levels.
1080Sstevel@tonic-gate */
1090Sstevel@tonic-gate if (ps_pread(php, db_privp, (char *)&db_priv,
1100Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
1110Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
1122712Snn35248 EC_ADDR(db_privp)));
1130Sstevel@tonic-gate return (RD_DBERR);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
1170Sstevel@tonic-gate (db_priv.rtd_version > R_RTLDDB_VERSION)) {
1180Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
1192712Snn35248 db_priv.rtd_version, R_RTLDDB_VERSION));
1200Sstevel@tonic-gate return (RD_NOCAPAB);
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate * Is the image being examined from a core file or not.
1250Sstevel@tonic-gate * If it is a core file then the following write will fail.
1260Sstevel@tonic-gate */
1270Sstevel@tonic-gate if (ps_pwrite(php, db_privp, (char *)&db_priv,
1280Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK)
1290Sstevel@tonic-gate rap->rd_flags |= RDF_FL_COREFILE;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate rap->rd_rdebugvers = db_priv.rtd_version;
1320Sstevel@tonic-gate rap->rd_rtlddbpriv = db_privp;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
1352712Snn35248 R_RTLDDB_VERSION, rap->rd_rdebugvers,
1362712Snn35248 rap->rd_flags & RDF_FL_COREFILE));
1370Sstevel@tonic-gate return (RD_OK);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate rd_err_e
find_dynamic_ent32(struct rd_agent * rap,psaddr_t dynaddr,Xword dyntag,Dyn * dyn)1420Sstevel@tonic-gate find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
1430Sstevel@tonic-gate Xword dyntag, Dyn *dyn)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp;
1460Sstevel@tonic-gate Dyn d;
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate d.d_tag = DT_NULL;
1490Sstevel@tonic-gate do {
1500Sstevel@tonic-gate if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
1510Sstevel@tonic-gate PS_OK) {
1520Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
1532712Snn35248 EC_ADDR(dynaddr)));
1540Sstevel@tonic-gate return (RD_DBERR);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate dynaddr += sizeof (d);
1570Sstevel@tonic-gate if (d.d_tag == dyntag)
1580Sstevel@tonic-gate break;
1590Sstevel@tonic-gate } while (d.d_tag != DT_NULL);
1600Sstevel@tonic-gate if (d.d_tag == dyntag) {
1610Sstevel@tonic-gate *dyn = d;
1620Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
1630Sstevel@tonic-gate EC_ADDR(d.d_un.d_val)));
1640Sstevel@tonic-gate return (RD_OK);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
1670Sstevel@tonic-gate return (RD_DBERR);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate
1702712Snn35248 extern char rtld_db_helper_path[MAXPATHLEN];
1712712Snn35248
1720Sstevel@tonic-gate rd_err_e
_rd_reset32(struct rd_agent * rap)1730Sstevel@tonic-gate _rd_reset32(struct rd_agent *rap)
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate psaddr_t symaddr;
1760Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp;
1770Sstevel@tonic-gate const auxv_t *auxvp = NULL;
1780Sstevel@tonic-gate rd_err_e rc = RD_OK;
1792712Snn35248 char brandname[MAXPATHLEN];
1802712Snn35248 char brandlib[MAXPATHLEN];
1815041Sedp ps_pbrandname_fp_t ps_pbrandname;
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate /*
1840Sstevel@tonic-gate * librtld_db attempts three different methods to find
1850Sstevel@tonic-gate * the r_debug structure which is required to
1860Sstevel@tonic-gate * initialize itself. The methods are:
1870Sstevel@tonic-gate * method1:
1880Sstevel@tonic-gate * entirely independent of any text segment
1890Sstevel@tonic-gate * and relies on the AT_SUN_LDDATA auxvector
1900Sstevel@tonic-gate * to find the ld.so.1::rdebug structure.
1910Sstevel@tonic-gate * method2:
1920Sstevel@tonic-gate * lookup symbols in ld.so.1's symbol table
1930Sstevel@tonic-gate * to find the r_debug symbol.
1940Sstevel@tonic-gate * method3:
1950Sstevel@tonic-gate * (old dbx method) dependent upon the
1960Sstevel@tonic-gate * text segment/symbol table of the
1970Sstevel@tonic-gate * executable and not ld.so.1. We lookup the
1980Sstevel@tonic-gate * _DYNAMIC symbol in the executable and look for
1990Sstevel@tonic-gate * the DT_DEBUG entry in the .dynamic table. This
2000Sstevel@tonic-gate * points to rdebug.
2010Sstevel@tonic-gate *
2020Sstevel@tonic-gate * If none of that works - we fail.
2030Sstevel@tonic-gate */
2040Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
2050Sstevel@tonic-gate /*
2060Sstevel@tonic-gate * Method1
2070Sstevel@tonic-gate *
2080Sstevel@tonic-gate * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
2090Sstevel@tonic-gate */
2102712Snn35248
2110Sstevel@tonic-gate if (ps_pauxv(php, &auxvp) != PS_OK) {
2120Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
2130Sstevel@tonic-gate rc = RD_ERR;
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate rap->rd_rdebug = 0;
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate if (auxvp != NULL) {
2190Sstevel@tonic-gate rc = RD_ERR;
2200Sstevel@tonic-gate while (auxvp->a_type != AT_NULL) {
2210Sstevel@tonic-gate if (auxvp->a_type == AT_SUN_LDDATA) {
2220Sstevel@tonic-gate /* LINTED */
2230Sstevel@tonic-gate rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
2240Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
2250Sstevel@tonic-gate rap->rd_rdebug));
2266830Sedp rc = validate_rdebug32(rap);
2270Sstevel@tonic-gate break;
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate auxvp++;
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate * method2 - look for r_rdebug symbol in ld.so.1
2350Sstevel@tonic-gate */
2360Sstevel@tonic-gate if (rc != RD_OK) {
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate * If the AT_SUN_LDDATA auxv vector is not present
2390Sstevel@tonic-gate * fall back on doing a symlookup of
2400Sstevel@tonic-gate * the r_debug symbol. This is for backward
2410Sstevel@tonic-gate * compatiblity with older OS's
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
2440Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
2450Sstevel@tonic-gate &symaddr) != PS_OK) {
2460Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
2472712Snn35248 MSG_ORIG(MSG_SYM_DEBUG)));
2480Sstevel@tonic-gate rc = RD_DBERR;
2490Sstevel@tonic-gate } else {
2500Sstevel@tonic-gate rap->rd_rdebug = symaddr;
2510Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
2522712Snn35248 EC_ADDR(symaddr)));
2536830Sedp rc = validate_rdebug32(rap);
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate * method3 - find DT_DEBUG in the executables .dynamic section.
2600Sstevel@tonic-gate */
2610Sstevel@tonic-gate if (rc != RD_OK) {
2620Sstevel@tonic-gate Dyn dyn;
2630Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
2640Sstevel@tonic-gate MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
2650Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
2660Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2670Sstevel@tonic-gate return (rc);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
2700Sstevel@tonic-gate if (rc != RD_OK) {
2710Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2720Sstevel@tonic-gate return (rc);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate rap->rd_rdebug = dyn.d_un.d_ptr;
2756830Sedp rc = validate_rdebug32(rap);
2760Sstevel@tonic-gate if (rc != RD_OK) {
2770Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
2780Sstevel@tonic-gate return (rc);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate
2822712Snn35248 /*
2836830Sedp * If we are debugging a branded executable, load the appropriate
2846830Sedp * helper library, and call its initialization routine. Being unable
2856830Sedp * to load the helper library is not a critical error. (Hopefully
2866830Sedp * we'll still be able to access some objects in the target.)
2872712Snn35248 */
2885041Sedp ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
2896830Sedp while ((ps_pbrandname != NULL) &&
2905041Sedp (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
2912712Snn35248 const char *isa = "";
2922712Snn35248
2936830Sedp #ifdef _LP64
2942712Snn35248 isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
2956830Sedp #endif /* _LP64 */
2962712Snn35248
2972712Snn35248 if (rtld_db_helper_path[0] != '\0')
2982712Snn35248 (void) snprintf(brandlib, MAXPATHLEN,
2992712Snn35248 MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
3002712Snn35248 rtld_db_helper_path,
3012712Snn35248 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
3022712Snn35248 brandname);
3032712Snn35248 else
3042712Snn35248 (void) snprintf(brandlib, MAXPATHLEN,
3052712Snn35248 MSG_ORIG(MSG_DB_BRAND_HELPERPATH),
3062712Snn35248 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
3072712Snn35248 brandname);
3082712Snn35248
3096830Sedp rap->rd_helper.rh_dlhandle = dlopen(brandlib,
3106830Sedp RTLD_LAZY | RTLD_LOCAL);
3116830Sedp if (rap->rd_helper.rh_dlhandle == NULL) {
3122712Snn35248 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
3132712Snn35248 brandlib));
3146830Sedp break;
3152712Snn35248 }
3162712Snn35248
3176830Sedp rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
3186830Sedp MSG_ORIG(MSG_SYM_BRANDOPS));
3196830Sedp if (rap->rd_helper.rh_ops == NULL) {
3202712Snn35248 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
3212712Snn35248 brandlib));
3226830Sedp (void) dlclose(rap->rd_helper.rh_dlhandle);
3236830Sedp rap->rd_helper.rh_dlhandle = NULL;
3246830Sedp break;
3252712Snn35248 }
3262712Snn35248
3276830Sedp rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
3286830Sedp php);
3292712Snn35248 if (rap->rd_helper.rh_data == NULL) {
3302712Snn35248 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
3312712Snn35248 (void) dlclose(rap->rd_helper.rh_dlhandle);
3322712Snn35248 rap->rd_helper.rh_dlhandle = NULL;
3332712Snn35248 rap->rd_helper.rh_ops = NULL;
3346830Sedp break;
3356830Sedp }
3366830Sedp
3376830Sedp LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
3386830Sedp break;
3396874Srie
3406874Srie /* NOTREACHED */
3412712Snn35248 }
3422712Snn35248
3430Sstevel@tonic-gate if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
3440Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3450Sstevel@tonic-gate MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
3460Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3472712Snn35248 MSG_ORIG(MSG_SYM_PREINIT)));
3480Sstevel@tonic-gate return (RD_DBERR);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate rap->rd_preinit = symaddr;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3530Sstevel@tonic-gate MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
3540Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3552712Snn35248 MSG_ORIG(MSG_SYM_POSTINIT)));
3560Sstevel@tonic-gate return (RD_DBERR);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate rap->rd_postinit = symaddr;
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
3610Sstevel@tonic-gate MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
3620Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
3632712Snn35248 MSG_ORIG(MSG_SYM_DLACT)));
3640Sstevel@tonic-gate return (RD_DBERR);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate rap->rd_dlact = symaddr;
3670Sstevel@tonic-gate rap->rd_tbinder = 0;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate return (RD_OK);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate rd_err_e
_rd_get_ehdr32(struct rd_agent * rap,psaddr_t addr,Ehdr * ehdr,uint_t * phnum)3746830Sedp _rd_get_ehdr32(struct rd_agent *rap,
3756830Sedp psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
3766830Sedp {
3776830Sedp struct ps_prochandle *php = rap->rd_psp;
3786830Sedp Shdr shdr;
3796830Sedp
3806830Sedp if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
3816830Sedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
3826830Sedp return (RD_ERR);
3836830Sedp }
3846830Sedp if (phnum == NULL)
3856830Sedp return (RD_OK);
3866830Sedp
3876830Sedp if (ehdr->e_phnum != PN_XNUM) {
3886830Sedp *phnum = ehdr->e_phnum;
3896830Sedp return (RD_OK);
3906830Sedp }
3916830Sedp
3926830Sedp /* deal with elf extended program headers */
3936830Sedp if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
3946830Sedp return (RD_ERR);
3956830Sedp
3966830Sedp addr += ehdr->e_shoff;
3976830Sedp if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
3986830Sedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
3996830Sedp return (RD_ERR);
4006830Sedp }
4016830Sedp
4026830Sedp if (shdr.sh_info == 0)
4036830Sedp return (RD_ERR);
4046830Sedp
4056830Sedp *phnum = shdr.sh_info;
4066830Sedp return (RD_OK);
4076830Sedp }
4086830Sedp
4096830Sedp rd_err_e
_rd_get_dyns32(rd_agent_t * rap,psaddr_t addr,Dyn ** dynpp,size_t * dynpp_sz)4106830Sedp _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
4116830Sedp {
4126830Sedp struct ps_prochandle *php = rap->rd_psp;
4136830Sedp rd_err_e err;
4146830Sedp uint_t phnum;
4156830Sedp Ehdr ehdr;
4166830Sedp Phdr phdr;
4176830Sedp Dyn *dynp;
4186830Sedp int i;
4196830Sedp
4206830Sedp /* We only need to muck with dyn elements for ET_DYN objects */
4216830Sedp if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
4226830Sedp return (err);
4236830Sedp
4246830Sedp for (i = 0; i < phnum; i++) {
4256830Sedp psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
4266830Sedp if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
4276830Sedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
4286830Sedp return (RD_ERR);
4296830Sedp }
4306830Sedp if (phdr.p_type == PT_DYNAMIC)
4316830Sedp break;
4326830Sedp }
4336830Sedp if (i == phnum)
4346830Sedp return (RD_ERR);
4356830Sedp
4366830Sedp if ((dynp = malloc(phdr.p_filesz)) == NULL)
4376830Sedp return (RD_ERR);
4386830Sedp if (ehdr.e_type == ET_DYN)
4396830Sedp phdr.p_vaddr += addr;
4406830Sedp if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
4416830Sedp free(dynp);
4426830Sedp LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
4436830Sedp EC_ADDR(phdr.p_vaddr)));
4446830Sedp return (RD_ERR);
4456830Sedp }
4466830Sedp
4476830Sedp *dynpp = dynp;
4486868Sedp if (dynpp_sz != NULL)
4496868Sedp *dynpp_sz = phdr.p_filesz;
4506830Sedp return (RD_OK);
4516830Sedp }
4526830Sedp
4536830Sedp rd_err_e
_rd_event_enable32(rd_agent_t * rap,int onoff)4540Sstevel@tonic-gate _rd_event_enable32(rd_agent_t *rap, int onoff)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp;
4570Sstevel@tonic-gate Rtld_db_priv rdb;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate * Tell the debugged process that debugging is occuring
4620Sstevel@tonic-gate * This will enable the storing of event messages so that
4630Sstevel@tonic-gate * the can be gathered by the debugger.
4640Sstevel@tonic-gate */
4650Sstevel@tonic-gate if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
4660Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
4670Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
4680Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb)));
4690Sstevel@tonic-gate return (RD_DBERR);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate if (onoff)
4730Sstevel@tonic-gate rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
4740Sstevel@tonic-gate else
4750Sstevel@tonic-gate rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
4780Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
4790Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
4800Sstevel@tonic-gate EC_ADDR((uintptr_t)&rdb)));
4810Sstevel@tonic-gate return (RD_DBERR);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate return (RD_OK);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate rd_err_e
_rd_event_getmsg32(rd_agent_t * rap,rd_event_msg_t * emsg)4890Sstevel@tonic-gate _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate Rtld_db_priv rdb;
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
4940Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
4950Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
4960Sstevel@tonic-gate EC_ADDR(rap->rd_rdebug)));
4970Sstevel@tonic-gate return (RD_DBERR);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate emsg->type = rdb.rtd_rdebug.r_rdevent;
5000Sstevel@tonic-gate if (emsg->type == RD_DLACTIVITY) {
5010Sstevel@tonic-gate switch (rdb.rtd_rdebug.r_state) {
5020Sstevel@tonic-gate case RT_CONSISTENT:
5030Sstevel@tonic-gate emsg->u.state = RD_CONSISTENT;
5040Sstevel@tonic-gate break;
5050Sstevel@tonic-gate case RT_ADD:
5060Sstevel@tonic-gate emsg->u.state = RD_ADD;
5070Sstevel@tonic-gate break;
5080Sstevel@tonic-gate case RT_DELETE:
5090Sstevel@tonic-gate emsg->u.state = RD_DELETE;
5100Sstevel@tonic-gate break;
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate } else
5130Sstevel@tonic-gate emsg->u.state = RD_NOSTATE;
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
5162712Snn35248 emsg->type, emsg->u.state));
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate return (RD_OK);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate rd_err_e
_rd_objpad_enable32(struct rd_agent * rap,size_t padsize)5230Sstevel@tonic-gate _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
5240Sstevel@tonic-gate {
5250Sstevel@tonic-gate Rtld_db_priv db_priv;
5260Sstevel@tonic-gate struct ps_prochandle *php = rap->rd_psp;
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
5310Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
5320Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
5330Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv)));
5340Sstevel@tonic-gate return (RD_DBERR);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate #if defined(_LP64) && !defined(_ELF64)
5370Sstevel@tonic-gate /*LINTED*/
5380Sstevel@tonic-gate db_priv.rtd_objpad = (uint32_t)padsize;
5390Sstevel@tonic-gate #else
5400Sstevel@tonic-gate db_priv.rtd_objpad = padsize;
5410Sstevel@tonic-gate #endif
5420Sstevel@tonic-gate if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
5430Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
5440Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
5450Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv)));
5460Sstevel@tonic-gate return (RD_DBERR);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate return (RD_OK);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate static rd_err_e
iter_map(rd_agent_t * rap,unsigned long ident,psaddr_t lmaddr,rl_iter_f * cb,void * client_data,uint_t * abort_iterp)5520Sstevel@tonic-gate iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
5537924SEdward.Pilatowicz@Sun.COM rl_iter_f *cb, void *client_data, uint_t *abort_iterp)
5540Sstevel@tonic-gate {
5550Sstevel@tonic-gate while (lmaddr) {
5560Sstevel@tonic-gate Rt_map rmap;
5570Sstevel@tonic-gate rd_loadobj_t lobj;
5580Sstevel@tonic-gate int i;
5590Sstevel@tonic-gate ulong_t off;
5600Sstevel@tonic-gate Ehdr ehdr;
5610Sstevel@tonic-gate Phdr phdr;
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
5640Sstevel@tonic-gate sizeof (Rt_map)) != PS_OK) {
5650Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
5660Sstevel@tonic-gate return (RD_DBERR);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate * As of 'VERSION5' we only report objects
5710Sstevel@tonic-gate * which have been fully relocated. While the maps
5720Sstevel@tonic-gate * might be in a consistent state - if a object hasn't
5730Sstevel@tonic-gate * been relocated - it's not really ready for the debuggers
5740Sstevel@tonic-gate * to examine. This is mostly due to the fact that we
5750Sstevel@tonic-gate * might still be mucking with the text-segment, if
5760Sstevel@tonic-gate * we are - we could conflict with any break-points
5770Sstevel@tonic-gate * the debuggers might have set.
5780Sstevel@tonic-gate */
5790Sstevel@tonic-gate if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
5800Sstevel@tonic-gate if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
5810Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap);
5820Sstevel@tonic-gate continue;
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate lobj.rl_base = (psaddr_t)ADDR(&rmap);
5870Sstevel@tonic-gate lobj.rl_flags = 0;
5880Sstevel@tonic-gate lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
5896830Sedp if ((rap->rd_helper.rh_ops != NULL) &&
5906830Sedp (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
5916830Sedp lobj.rl_lmident =
5926830Sedp rap->rd_helper.rh_ops->rho_lmid;
5932712Snn35248 else
5942712Snn35248 lobj.rl_lmident = ident;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate /*
5970Sstevel@tonic-gate * refnameaddr is only valid from a core file
5980Sstevel@tonic-gate * which is VERSION3 or greater.
5990Sstevel@tonic-gate */
6000Sstevel@tonic-gate if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
6010Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
6020Sstevel@tonic-gate lobj.rl_bend = 0;
6030Sstevel@tonic-gate lobj.rl_padstart = 0;
6040Sstevel@tonic-gate lobj.rl_padend = 0;
6050Sstevel@tonic-gate } else {
6060Sstevel@tonic-gate lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
6070Sstevel@tonic-gate lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
6080Sstevel@tonic-gate lobj.rl_padstart = PADSTART(&rmap);
6090Sstevel@tonic-gate lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2)
6140Sstevel@tonic-gate if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
6150Sstevel@tonic-gate lobj.rl_flags |= RD_FLG_MEM_OBJECT;
6160Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION2) {
6170Sstevel@tonic-gate lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate if (rtld_db_version >= RD_VERSION4)
6210Sstevel@tonic-gate lobj.rl_tlsmodid = TLSMODID(&rmap);
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /*
6240Sstevel@tonic-gate * Look for beginning of data segment.
6250Sstevel@tonic-gate *
6260Sstevel@tonic-gate * NOTE: the data segment can only be found for full
6270Sstevel@tonic-gate * processes and not from core images.
6280Sstevel@tonic-gate */
6290Sstevel@tonic-gate lobj.rl_data_base = 0;
6300Sstevel@tonic-gate if (rap->rd_flags & RDF_FL_COREFILE)
6310Sstevel@tonic-gate lobj.rl_data_base = 0;
6320Sstevel@tonic-gate else {
6330Sstevel@tonic-gate off = ADDR(&rmap);
6340Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
6350Sstevel@tonic-gate sizeof (Ehdr)) != PS_OK) {
6360Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
6370Sstevel@tonic-gate return (RD_DBERR);
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate off += sizeof (Ehdr);
6400Sstevel@tonic-gate for (i = 0; i < ehdr.e_phnum; i++) {
6410Sstevel@tonic-gate if (ps_pread(rap->rd_psp, off, (char *)&phdr,
6420Sstevel@tonic-gate sizeof (Phdr)) != PS_OK) {
6430Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(
6440Sstevel@tonic-gate MSG_DB_LKMAPFAIL)));
6450Sstevel@tonic-gate return (RD_DBERR);
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate if ((phdr.p_type == PT_LOAD) &&
6480Sstevel@tonic-gate (phdr.p_flags & PF_W)) {
6490Sstevel@tonic-gate lobj.rl_data_base = phdr.p_vaddr;
6500Sstevel@tonic-gate if (ehdr.e_type == ET_DYN)
6510Sstevel@tonic-gate lobj.rl_data_base +=
6522712Snn35248 ADDR(&rmap);
6530Sstevel@tonic-gate break;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate off += ehdr.e_phentsize;
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * When we transfer control to the client we free the
6610Sstevel@tonic-gate * lock and re-atain it after we've returned from the
6620Sstevel@tonic-gate * client. This is to avoid any deadlock situations.
6630Sstevel@tonic-gate */
6640Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
6652712Snn35248 EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
6660Sstevel@tonic-gate RDAGUNLOCK(rap);
6670Sstevel@tonic-gate if ((*cb)(&lobj, client_data) == 0) {
6680Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
6690Sstevel@tonic-gate RDAGLOCK(rap);
6707924SEdward.Pilatowicz@Sun.COM *abort_iterp = 1;
6710Sstevel@tonic-gate break;
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate RDAGLOCK(rap);
6740Sstevel@tonic-gate lmaddr = (psaddr_t)NEXT(&rmap);
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate return (RD_OK);
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate
6807924SEdward.Pilatowicz@Sun.COM static rd_err_e
_rd_loadobj_iter32_native(rd_agent_t * rap,rl_iter_f * cb,void * client_data,uint_t * abort_iterp)6817924SEdward.Pilatowicz@Sun.COM _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data,
6827924SEdward.Pilatowicz@Sun.COM uint_t *abort_iterp)
6830Sstevel@tonic-gate {
6840Sstevel@tonic-gate Rtld_db_priv db_priv;
6859131SRod.Evans@Sun.COM TAPlist apl;
6869131SRod.Evans@Sun.COM uintptr_t datap, nitems;
6879131SRod.Evans@Sun.COM Addr addr;
6880Sstevel@tonic-gate rd_err_e rc;
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
6912712Snn35248 client_data));
6920Sstevel@tonic-gate
6939218SRod.Evans@Sun.COM /*
6949218SRod.Evans@Sun.COM * First, determine whether the link-map information has been
6959218SRod.Evans@Sun.COM * established. Some debuggers have made an initial call to this
6969218SRod.Evans@Sun.COM * function with a null call back function (cb), but expect a
6979218SRod.Evans@Sun.COM * RD_NOMAPS error return rather than a RD_ERR return when the
6989218SRod.Evans@Sun.COM * link-maps aren't available.
6999218SRod.Evans@Sun.COM */
7000Sstevel@tonic-gate if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
7010Sstevel@tonic-gate sizeof (Rtld_db_priv)) != PS_OK) {
7020Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
7030Sstevel@tonic-gate EC_ADDR(rap->rd_rtlddbpriv)));
7040Sstevel@tonic-gate return (RD_DBERR);
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate
7079131SRod.Evans@Sun.COM if (db_priv.rtd_dynlmlst == NULL) {
7080Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
7092712Snn35248 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7100Sstevel@tonic-gate return (RD_NOMAPS);
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate
7139131SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr,
7149131SRod.Evans@Sun.COM sizeof (Addr)) != PS_OK) {
7150Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
7162712Snn35248 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7170Sstevel@tonic-gate return (RD_DBERR);
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate
7209131SRod.Evans@Sun.COM if (addr == NULL) {
7210Sstevel@tonic-gate LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
7229131SRod.Evans@Sun.COM EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
7230Sstevel@tonic-gate return (RD_NOMAPS);
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate
7269218SRod.Evans@Sun.COM /*
7279218SRod.Evans@Sun.COM * Having determined we have link-maps, ensure we have an iterator
7289218SRod.Evans@Sun.COM * call back function.
7299218SRod.Evans@Sun.COM */
7309218SRod.Evans@Sun.COM if (cb == NULL) {
7319218SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
7329218SRod.Evans@Sun.COM return (RD_ERR);
7339218SRod.Evans@Sun.COM }
7349218SRod.Evans@Sun.COM
7359218SRod.Evans@Sun.COM /*
73610167SRod.Evans@Sun.COM * As of VERSION6, rtd_dynlmlst points to an APlist. Prior to VERSION6
73710167SRod.Evans@Sun.COM * rtd_dynlmlst pointed to a List. But, there was a window where the
73810167SRod.Evans@Sun.COM * version was not incremented, and this must be worked around by
73910167SRod.Evans@Sun.COM * interpreting the APlist data. Read the initial APlist information.
7409218SRod.Evans@Sun.COM */
7419131SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl,
7429131SRod.Evans@Sun.COM sizeof (TAPlist)) != PS_OK) {
7439131SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
7449131SRod.Evans@Sun.COM EC_ADDR((uintptr_t)addr)));
7459131SRod.Evans@Sun.COM return (RD_DBERR);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7489131SRod.Evans@Sun.COM /*
74910167SRod.Evans@Sun.COM * The rtd_dynlmlst change from a List to an APlist occurred under
75010167SRod.Evans@Sun.COM * 6801536 in snv_112. However, this change neglected to preserve
75110167SRod.Evans@Sun.COM * backward compatibility by maintaining List processing and using a
75210167SRod.Evans@Sun.COM * version increment to detect the change. 6862967, intergrated in
75310167SRod.Evans@Sun.COM * snv_121 corrects the version detection. However, to catch objects
75410167SRod.Evans@Sun.COM * built between these releases, we look at the first element of the
75510167SRod.Evans@Sun.COM * APlist. apl_arritems indicates the number of APlist items that are
75610167SRod.Evans@Sun.COM * available. This was originally initialized with a AL_CNT_DYNLIST
75710167SRod.Evans@Sun.COM * value of 2 (one entry for LM_ID_BASE and one entry for LM_ID_LDSO).
75810167SRod.Evans@Sun.COM * It is possible that the use of an auditor results in an additional
75910167SRod.Evans@Sun.COM * link-map list, in which case the original apl_arritems would have
76010167SRod.Evans@Sun.COM * been doubled.
76110167SRod.Evans@Sun.COM *
76210167SRod.Evans@Sun.COM * Therefore, if the debugging verion is VERSION6, or the apl_arritems
76310167SRod.Evans@Sun.COM * entry has a value less than or equal to 4 and the debugging version
76410167SRod.Evans@Sun.COM * is VERSION5, then we process APlists. Otherwise, fall back to List
76510167SRod.Evans@Sun.COM * processing.
7669131SRod.Evans@Sun.COM */
76710167SRod.Evans@Sun.COM if ((rap->rd_rdebugvers >= R_RTLDDB_VERSION6) ||
76810167SRod.Evans@Sun.COM ((rap->rd_rdebugvers == R_RTLDDB_VERSION5) &&
76910167SRod.Evans@Sun.COM (apl.apl_arritems <= 4))) {
77010167SRod.Evans@Sun.COM /*
77110167SRod.Evans@Sun.COM * Iterate through each apl.ap_data[] entry.
77210167SRod.Evans@Sun.COM */
77310167SRod.Evans@Sun.COM for (datap = (uintptr_t)((char *)(uintptr_t)addr +
77410167SRod.Evans@Sun.COM ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0;
77510167SRod.Evans@Sun.COM nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) {
77610167SRod.Evans@Sun.COM TLm_list lm;
77710167SRod.Evans@Sun.COM ulong_t ident;
77810167SRod.Evans@Sun.COM
77910167SRod.Evans@Sun.COM /*
78010167SRod.Evans@Sun.COM * Obtain the Lm_list address for this apl.ap_data[]
78110167SRod.Evans@Sun.COM * entry.
78210167SRod.Evans@Sun.COM */
78310167SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)datap,
78410167SRod.Evans@Sun.COM (char *)&addr, sizeof (Addr)) != PS_OK) {
78510167SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
78610167SRod.Evans@Sun.COM EC_ADDR(datap)));
78710167SRod.Evans@Sun.COM return (RD_DBERR);
78810167SRod.Evans@Sun.COM }
78910167SRod.Evans@Sun.COM
79010167SRod.Evans@Sun.COM /*
79110167SRod.Evans@Sun.COM * Obtain the Lm_list data for this Lm_list address.
79210167SRod.Evans@Sun.COM */
79310167SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm,
79410167SRod.Evans@Sun.COM sizeof (TLm_list)) != PS_OK) {
79510167SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6),
79610167SRod.Evans@Sun.COM EC_ADDR((uintptr_t)addr)));
79710167SRod.Evans@Sun.COM return (RD_DBERR);
79810167SRod.Evans@Sun.COM }
79910167SRod.Evans@Sun.COM
80010167SRod.Evans@Sun.COM /*
80110167SRod.Evans@Sun.COM * Determine IDENT of current LM_LIST
80210167SRod.Evans@Sun.COM */
80310167SRod.Evans@Sun.COM if (lm.lm_flags & LML_FLG_BASELM)
80410167SRod.Evans@Sun.COM ident = LM_ID_BASE;
80510167SRod.Evans@Sun.COM else if (lm.lm_flags & LML_FLG_RTLDLM)
80610167SRod.Evans@Sun.COM ident = LM_ID_LDSO;
80710167SRod.Evans@Sun.COM else
80810167SRod.Evans@Sun.COM ident = (ulong_t)addr;
80910167SRod.Evans@Sun.COM
81010167SRod.Evans@Sun.COM if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head,
81110167SRod.Evans@Sun.COM cb, client_data, abort_iterp)) != RD_OK)
81210167SRod.Evans@Sun.COM return (rc);
81310167SRod.Evans@Sun.COM
81410167SRod.Evans@Sun.COM if (*abort_iterp != 0)
81510167SRod.Evans@Sun.COM break;
81610167SRod.Evans@Sun.COM }
81710167SRod.Evans@Sun.COM } else {
81810167SRod.Evans@Sun.COM TList list;
81910167SRod.Evans@Sun.COM TListnode lnode;
82010167SRod.Evans@Sun.COM Addr lnp;
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate /*
82310167SRod.Evans@Sun.COM * Re-read the dynlmlst address to obtain a List structure.
8240Sstevel@tonic-gate */
82510167SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst,
82610167SRod.Evans@Sun.COM (char *)&list, sizeof (TList)) != PS_OK) {
82710167SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
82810167SRod.Evans@Sun.COM EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
8290Sstevel@tonic-gate return (RD_DBERR);
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate
8329131SRod.Evans@Sun.COM /*
83310167SRod.Evans@Sun.COM * Iterate through the link-map list.
8340Sstevel@tonic-gate */
83510167SRod.Evans@Sun.COM for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
83610167SRod.Evans@Sun.COM Lm_list lml;
83710167SRod.Evans@Sun.COM ulong_t ident;
83810167SRod.Evans@Sun.COM
83910167SRod.Evans@Sun.COM /*
84010167SRod.Evans@Sun.COM * Iterate through the List of Lm_list's.
84110167SRod.Evans@Sun.COM */
84210167SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
84310167SRod.Evans@Sun.COM sizeof (TListnode)) != PS_OK) {
84410167SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
84510167SRod.Evans@Sun.COM EC_ADDR(lnp)));
84610167SRod.Evans@Sun.COM return (RD_DBERR);
84710167SRod.Evans@Sun.COM }
8480Sstevel@tonic-gate
84910167SRod.Evans@Sun.COM if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data,
85010167SRod.Evans@Sun.COM (char *)&lml, sizeof (Lm_list)) != PS_OK) {
85110167SRod.Evans@Sun.COM LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
85210167SRod.Evans@Sun.COM EC_ADDR((uintptr_t)lnode.data)));
85310167SRod.Evans@Sun.COM return (RD_DBERR);
85410167SRod.Evans@Sun.COM }
85510167SRod.Evans@Sun.COM
85610167SRod.Evans@Sun.COM /*
85710167SRod.Evans@Sun.COM * Determine IDENT of current LM_LIST
85810167SRod.Evans@Sun.COM */
85910167SRod.Evans@Sun.COM if (lml.lm_flags & LML_FLG_BASELM)
86010167SRod.Evans@Sun.COM ident = LM_ID_BASE;
86110167SRod.Evans@Sun.COM else if (lml.lm_flags & LML_FLG_RTLDLM)
86210167SRod.Evans@Sun.COM ident = LM_ID_LDSO;
86310167SRod.Evans@Sun.COM else
86410167SRod.Evans@Sun.COM ident = (unsigned long)lnode.data;
86510167SRod.Evans@Sun.COM
86610167SRod.Evans@Sun.COM if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
86710167SRod.Evans@Sun.COM cb, client_data, abort_iterp)) != RD_OK)
86810167SRod.Evans@Sun.COM return (rc);
86910167SRod.Evans@Sun.COM
87010167SRod.Evans@Sun.COM if (*abort_iterp != 0)
87110167SRod.Evans@Sun.COM break;
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate }
8742712Snn35248
8757924SEdward.Pilatowicz@Sun.COM return (rc);
8767924SEdward.Pilatowicz@Sun.COM }
8777924SEdward.Pilatowicz@Sun.COM
8787924SEdward.Pilatowicz@Sun.COM rd_err_e
_rd_loadobj_iter32(rd_agent_t * rap,rl_iter_f * cb,void * client_data)8797924SEdward.Pilatowicz@Sun.COM _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
8807924SEdward.Pilatowicz@Sun.COM {
8818478SRod.Evans@Sun.COM rd_err_e rc, rc_brand = RD_OK;
8827924SEdward.Pilatowicz@Sun.COM uint_t abort_iter = 0;
8837924SEdward.Pilatowicz@Sun.COM
8847924SEdward.Pilatowicz@Sun.COM /* First iterate over the native target objects */
8857924SEdward.Pilatowicz@Sun.COM rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter);
8867924SEdward.Pilatowicz@Sun.COM if (abort_iter != 0)
8872712Snn35248 return (rc);
8882712Snn35248
8897924SEdward.Pilatowicz@Sun.COM /* Then iterate over any branded objects. */
8907924SEdward.Pilatowicz@Sun.COM if ((rap->rd_helper.rh_ops != NULL) &&
8917924SEdward.Pilatowicz@Sun.COM (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL))
8927924SEdward.Pilatowicz@Sun.COM rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter(
8937924SEdward.Pilatowicz@Sun.COM rap->rd_helper.rh_data, cb, client_data);
8942712Snn35248
8958478SRod.Evans@Sun.COM rc = (rc != RD_OK) ? rc : rc_brand;
8967924SEdward.Pilatowicz@Sun.COM return (rc);
8970Sstevel@tonic-gate }
898