Home | History | Annotate | Download | only in common
      1  2712  nn35248 /*
      2  2712  nn35248  * CDDL HEADER START
      3  2712  nn35248  *
      4  2712  nn35248  * The contents of this file are subject to the terms of the
      5  2712  nn35248  * Common Development and Distribution License (the "License").
      6  2712  nn35248  * You may not use this file except in compliance with the License.
      7  2712  nn35248  *
      8  2712  nn35248  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  2712  nn35248  * or http://www.opensolaris.org/os/licensing.
     10  2712  nn35248  * See the License for the specific language governing permissions
     11  2712  nn35248  * and limitations under the License.
     12  2712  nn35248  *
     13  2712  nn35248  * When distributing Covered Code, include this CDDL HEADER in each
     14  2712  nn35248  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  2712  nn35248  * If applicable, add the following below this CDDL HEADER, with the
     16  2712  nn35248  * fields enclosed by brackets "[]" replaced with your own identifying
     17  2712  nn35248  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  2712  nn35248  *
     19  2712  nn35248  * CDDL HEADER END
     20  2712  nn35248  */
     21  2712  nn35248 /*
     22  6473      edp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  2712  nn35248  * Use is subject to license terms.
     24  2712  nn35248  */
     25  2712  nn35248 
     26  2712  nn35248 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27  2712  nn35248 
     28  2712  nn35248 #include <stdio.h>
     29  2712  nn35248 #include <stdlib.h>
     30  2712  nn35248 #include <string.h>
     31  2712  nn35248 #include <strings.h>
     32  2712  nn35248 #include <sys/types.h>
     33  2712  nn35248 #include <sys/link.h>
     34  2712  nn35248 #include <libproc.h>
     35  2712  nn35248 #include <proc_service.h>
     36  2712  nn35248 #include <rtld_db.h>
     37  2712  nn35248 #include <synch.h>
     38  6830      edp 
     39  2712  nn35248 #include <sys/lx_brand.h>
     40  2712  nn35248 
     41  6830      edp /*
     42  6830      edp  * ATTENTION:
     43  6830      edp  *	Librtl_db brand plugin libraries should NOT directly invoke any
     44  6830      edp  *	libproc.so interfaces or be linked against libproc.  If a librtl_db
     45  6830      edp  *	brand plugin library uses libproc.so interfaces then it may break
     46  6830      edp  *	any other librtld_db consumers (like mdb) that tries to attach
     47  6830      edp  *	to a branded process.  The only safe interfaces that the a librtld_db
     48  6830      edp  *	brand plugin library can use to access a target process are the
     49  6830      edp  *	proc_service(3PROC) apis.
     50  6830      edp  */
     51  2712  nn35248 
     52  6830      edp /*
     53  6830      edp  * M_DATA comes from some streams header file but is also redifined in
     54  6830      edp  * _rtld_db.h, so nuke the old streams definition here.
     55  6830      edp  */
     56  6830      edp #ifdef M_DATA
     57  6830      edp #undef M_DATA
     58  6830      edp #endif /* M_DATA */
     59  6830      edp 
     60  6830      edp /*
     61  6830      edp  * For 32-bit versions of this library, this file get's compiled once.
     62  6830      edp  * For 64-bit versions of this library, this file get's compiled twice,
     63  6830      edp  * once with _ELF64 defined and once without.  The expectation is that
     64  6830      edp  * the 64-bit version of the library can properly deal with both 32-bit
     65  6830      edp  * and 64-bit elf files, hence in the 64-bit library there are two copies
     66  6830      edp  * of all the interfaces in this file, one set named *32 and one named *64.
     67  6830      edp  *
     68  6830      edp  * This also means that we need to be careful when declaring local pointers
     69  6830      edp  * that point to objects in another processes address space, since these
     70  6830      edp  * pointers may not match the current processes pointer width.  Basically,
     71  6830      edp  * we should avoid using data types that change size between 32 and 64 bit
     72  6830      edp  * modes like: long, void *, uintprt_t, caddr_t, psaddr_t, size_t, etc.
     73  6830      edp  * Instead we should declare all pointers as uint32_t.  Then when we
     74  6830      edp  * are compiled to deal with 64-bit targets we'll re-define uint32_t
     75  6830      edp  * to be a uint64_t.
     76  6830      edp  *
     77  6830      edp  * Finally, one last importante note.  All the 64-bit elf file code
     78  6830      edp  * is never used and can't be tested.  This is because we don't actually
     79  6830      edp  * support 64-bit Linux processes yet.  The reason that we have it here
     80  6830      edp  * is because we want to support debugging 32-bit elf targets with the
     81  6830      edp  * 64-bit version of this library, so we need to have a 64-bit version
     82  6830      edp  * of this library.  But a 64-bit version of this library is expected
     83  6830      edp  * to provide debugging interfaces for both 32 and 64-bit elf targets.
     84  6830      edp  * So we provide the 64-bit elf target interfaces, but they will never
     85  6830      edp  * be invoked and are untested.  If we ever add support for 64-bit elf
     86  6830      edp  * Linux processes, we'll need to verify that this code works correctly
     87  6830      edp  * for those targets.
     88  6830      edp  */
     89  6830      edp #ifdef _LP64
     90  6830      edp #ifdef _ELF64
     91  6830      edp #define	lx_ldb_get_dyns32		lx_ldb_get_dyns64
     92  6830      edp #define	lx_ldb_init32			lx_ldb_init64
     93  6830      edp #define	lx_ldb_fini32			lx_ldb_fini64
     94  6830      edp #define	lx_ldb_loadobj_iter32		lx_ldb_loadobj_iter64
     95  6830      edp #define	lx_ldb_getauxval32		lx_ldb_getauxval64
     96  6830      edp #define	lx_elf_props32			lx_elf_props64
     97  6830      edp #define	_rd_get_dyns32			_rd_get_dyns64
     98  6830      edp #define	_rd_get_ehdr32			_rd_get_ehdr64
     99  6830      edp #define	uint32_t			uint64_t
    100  6830      edp #define	Elf32_Dyn			Elf64_Dyn
    101  6830      edp #define	Elf32_Ehdr			Elf64_Ehdr
    102  6830      edp #define	Elf32_Phdr			Elf64_Phdr
    103  6830      edp #endif /* _ELF64 */
    104  6830      edp #endif /* _LP64 */
    105  6830      edp 
    106  6830      edp /* Included from usr/src/cmd/sgs/librtld_db/common */
    107  6830      edp #include <_rtld_db.h>
    108  2712  nn35248 
    109  2712  nn35248 typedef struct lx_rd {
    110  6830      edp 	rd_agent_t		*lr_rap;
    111  6830      edp 	struct ps_prochandle	*lr_php;	/* proc handle pointer */
    112  6830      edp 	uint32_t		lr_rdebug;	/* address of lx r_debug */
    113  6830      edp 	uint32_t		lr_exec;	/* base address of executable */
    114  2712  nn35248 } lx_rd_t;
    115  2712  nn35248 
    116  6830      edp typedef struct lx_link_map {
    117  2712  nn35248 	uint32_t lxm_addr;	/* Base address shared object is loaded at.  */
    118  2712  nn35248 	uint32_t lxm_name;	/* Absolute file name object was found in.  */
    119  2712  nn35248 	uint32_t lxm_ld;	/* Dynamic section of the shared object.  */
    120  6830      edp 	uint32_t lxm_next;	/* Chain of loaded objects.  */
    121  6830      edp } lx_link_map_t;
    122  2712  nn35248 
    123  6830      edp typedef struct lx_r_debug {
    124  2712  nn35248 	int r_version;		/* Version number for this protocol.  */
    125  2712  nn35248 	uint32_t	r_map;	/* Head of the chain of loaded objects. */
    126  2712  nn35248 
    127  2712  nn35248 	/*
    128  2712  nn35248 	 * This is the address of a function internal to the run-time linker,
    129  2712  nn35248 	 * that will always be called when the linker begins to map in a
    130  2712  nn35248 	 * library or unmap it, and again when the mapping change is complete.
    131  2712  nn35248 	 * The debugger can set a breakpoint at this address if it wants to
    132  2712  nn35248 	 * notice shared object mapping changes.
    133  2712  nn35248 	 */
    134  2712  nn35248 	uint32_t	r_brk;
    135  2712  nn35248 	r_state_e	r_state; /* defined the same way between lx/solaris */
    136  2712  nn35248 	uint32_t	r_ldbase; /* Base address the linker is loaded at. */
    137  6830      edp } lx_r_debug_t;
    138  6830      edp 
    139  6830      edp static uint32_t
    140  6830      edp lx_ldb_getauxval32(struct ps_prochandle *php, int type)
    141  6830      edp {
    142  6830      edp 	const auxv_t		*auxvp = NULL;
    143  6830      edp 
    144  6830      edp 	if (ps_pauxv(php, &auxvp) != PS_OK)
    145  6830      edp 		return ((uint32_t)-1);
    146  6830      edp 
    147  6830      edp 	while (auxvp->a_type != AT_NULL) {
    148  6830      edp 		if (auxvp->a_type == type)
    149  6830      edp 			return ((uint32_t)(uintptr_t)auxvp->a_un.a_ptr);
    150  6830      edp 		auxvp++;
    151  6830      edp 	}
    152  6830      edp 	return ((uint32_t)-1);
    153  6830      edp }
    154  2712  nn35248 
    155  2712  nn35248 /*
    156  2712  nn35248  * A key difference between the linux linker and ours' is that the linux
    157  2712  nn35248  * linker adds the base address of segments to certain values in the
    158  2712  nn35248  * segments' ELF header. As an example, look at the address of the
    159  2712  nn35248  * DT_HASH hash table in a Solaris section - it is a relative address
    160  2712  nn35248  * which locates the start of the hash table, relative to the beginning
    161  2712  nn35248  * of the ELF file. However, when the linux linker loads a section, it
    162  2712  nn35248  * modifies the in-memory ELF image by changing address of the hash
    163  2712  nn35248  * table to be an absolute address. This is only done for libraries - not for
    164  2712  nn35248  * executables.
    165  2712  nn35248  *
    166  2712  nn35248  * Solaris tools expect the relative address to remain relative, so
    167  2712  nn35248  * here we will modify the in-memory ELF image so that it once again
    168  2712  nn35248  * contains relative addresses.
    169  2712  nn35248  *
    170  2712  nn35248  * To accomplish this, we walk through all sections in the target.
    171  2712  nn35248  * Linux sections are identified by pointing to the linux linker or libc in the
    172  2712  nn35248  * DT_NEEDED section. For all matching sections, we subtract the segment
    173  2712  nn35248  * base address to get back to relative addresses.
    174  2712  nn35248  */
    175  6830      edp static rd_err_e
    176  6830      edp lx_ldb_get_dyns32(rd_helper_data_t rhd,
    177  6830      edp     psaddr_t addr, void **dynpp, size_t *dynpp_sz)
    178  2712  nn35248 {
    179  6830      edp 	lx_rd_t			*lx_rd = (lx_rd_t *)rhd;
    180  6830      edp 	rd_agent_t		*rap = lx_rd->lr_rap;
    181  6830      edp 	Elf32_Ehdr		ehdr;
    182  6830      edp 	Elf32_Dyn		*dynp = NULL;
    183  6830      edp 	size_t			dynp_sz;
    184  6830      edp 	uint_t			ndyns;
    185  2712  nn35248 	int			i;
    186  2712  nn35248 
    187  6830      edp 	ps_plog("lx_ldb_get_dyns: invoked for object at 0x%p", addr);
    188  6473      edp 
    189  6830      edp 	/* Read in a copy of the ehdr */
    190  6830      edp 	if (_rd_get_ehdr32(rap, addr, &ehdr, NULL) != RD_OK) {
    191  6830      edp 		ps_plog("lx_ldb_get_dyns: _rd_get_ehdr() failed");
    192  6830      edp 		return (RD_ERR);
    193  2712  nn35248 	}
    194  2712  nn35248 
    195  6830      edp 	/* read out the PT_DYNAMIC elements for this object */
    196  6830      edp 	if (_rd_get_dyns32(rap, addr, &dynp, &dynp_sz) != RD_OK) {
    197  6830      edp 		ps_plog("lx_ldb_get_dyns: _rd_get_dyns() failed");
    198  6830      edp 		return (RD_ERR);
    199  2712  nn35248 	}
    200  2712  nn35248 
    201  2712  nn35248 	/*
    202  6830      edp 	 * From here on out if we encounter an error we'll just return
    203  6830      edp 	 * success and pass back the unmolested dynamic elements that
    204  6830      edp 	 * we've already obtained.
    205  2712  nn35248 	 */
    206  6830      edp 	*dynpp = dynp;
    207  6830      edp 	*dynpp_sz = dynp_sz;
    208  6830      edp 	ndyns = dynp_sz / sizeof (Elf32_Dyn);
    209  2712  nn35248 
    210  6830      edp 	/* If this isn't a dynamic object, there's nothing left todo */
    211  6830      edp 	if (ehdr.e_type != ET_DYN) {
    212  6830      edp 		ps_plog("lx_ldb_get_dyns: done: not a shared object");
    213  6830      edp 		return (RD_OK);
    214  2712  nn35248 	}
    215  2712  nn35248 
    216  2712  nn35248 	/*
    217  6830      edp 	 * Before we blindly start changing dynamic section addresses
    218  6830      edp 	 * we need to figure out if the current object that we're looking
    219  6830      edp 	 * at is a linux object or a solaris object.  To do this first
    220  6830      edp 	 * we need to find the string tab dynamic section element.
    221  2712  nn35248 	 */
    222  6830      edp 	for (i = 0; i < ndyns; i++) {
    223  6830      edp 		if (dynp[i].d_tag == DT_STRTAB)
    224  6830      edp 			break;
    225  6830      edp 	}
    226  6830      edp 	if (i == ndyns) {
    227  6830      edp 		ps_plog("lx_ldb_get_dyns: "
    228  6830      edp 		    "failed to find string tab in the dynamic section");
    229  6830      edp 		return (RD_OK);
    230  6830      edp 	}
    231  6830      edp 
    232  6830      edp 	/*
    233  6830      edp 	 * Check if the strtab value looks like an offset or an address.
    234  6830      edp 	 * It's an offset if the value is less then the base address that
    235  6830      edp 	 * the object is loaded at, or if the value is less than the offset
    236  6830      edp 	 * of the section headers in the same elf object.  This check isn't
    237  6830      edp 	 * perfect, but in practice it's good enough.
    238  6830      edp 	 */
    239  6830      edp 	if ((dynp[i].d_un.d_ptr < addr) ||
    240  6830      edp 	    (dynp[i].d_un.d_ptr < ehdr.e_shoff)) {
    241  6830      edp 		ps_plog("lx_ldb_get_dyns: "
    242  6830      edp 		    "doesn't appear to be an lx object");
    243  6830      edp 		return (RD_OK);
    244  6830      edp 	}
    245  6830      edp 
    246  6830      edp 	/*
    247  6830      edp 	 * This seems to be a a linux object, so we'll patch up the dynamic
    248  6830      edp 	 * section addresses
    249  6830      edp 	 */
    250  6830      edp 	ps_plog("lx_ldb_get_dyns: "
    251  6830      edp 	    "patching up lx object dynamic section addresses");
    252  6830      edp 	for (i = 0; i < ndyns; i++) {
    253  6830      edp 		switch (dynp[i].d_tag) {
    254  6830      edp 		case DT_PLTGOT:
    255  2712  nn35248 		case DT_HASH:
    256  2712  nn35248 		case DT_STRTAB:
    257  2712  nn35248 		case DT_SYMTAB:
    258  6830      edp 		case DT_RELA:
    259  6830      edp 		case DT_REL:
    260  2712  nn35248 		case DT_DEBUG:
    261  2712  nn35248 		case DT_JMPREL:
    262  2712  nn35248 		case DT_VERSYM:
    263  6830      edp 			if (dynp[i].d_un.d_val > addr) {
    264  6830      edp 				dynp[i].d_un.d_ptr -= addr;
    265  2712  nn35248 			}
    266  2712  nn35248 			break;
    267  2712  nn35248 		default:
    268  2712  nn35248 			break;
    269  2712  nn35248 		}
    270  2712  nn35248 	}
    271  6830      edp 	return (RD_OK);
    272  6830      edp }
    273  6830      edp 
    274  6830      edp static void
    275  6830      edp lx_ldb_fini32(rd_helper_data_t rhd)
    276  6830      edp {
    277  6830      edp 	lx_rd_t *lx_rd = (lx_rd_t *)rhd;
    278  6830      edp 	ps_plog("lx_ldb_fini: cleaning up lx helper");
    279  6830      edp 	free(lx_rd);
    280  2712  nn35248 }
    281  2712  nn35248 
    282  2712  nn35248 /*
    283  2712  nn35248  * The linux linker has an r_debug structure somewhere in its data section that
    284  2712  nn35248  * contains the address of the head of the link map list. To find this, we will
    285  2712  nn35248  * use the DT_DEBUG token in the executable's dynamic section. The linux linker
    286  2712  nn35248  * wrote the address of its r_debug structure to the DT_DEBUG dynamic entry. We
    287  2712  nn35248  * get the address of the executable's program headers from the
    288  6473      edp  * AT_SUN_BRAND_LX_PHDR aux vector entry. From there, we calculate the
    289  6473      edp  * address of the Elf header, and from there we can easily get to the DT_DEBUG
    290  6473      edp  * entry.
    291  2712  nn35248  */
    292  6830      edp static rd_helper_data_t
    293  6830      edp lx_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php)
    294  2712  nn35248 {
    295  6830      edp 	lx_rd_t		*lx_rd;
    296  6830      edp 	uint32_t	addr, phdr_addr, dyn_addr;
    297  6830      edp 	Elf32_Dyn	*dyn;
    298  6473      edp 	Elf32_Phdr	phdr, *ph, *phdrs;
    299  2712  nn35248 	Elf32_Ehdr	ehdr;
    300  6830      edp 	int		i, dyn_count;
    301  2712  nn35248 
    302  6830      edp 	lx_rd = calloc(sizeof (lx_rd_t), 1);
    303  6830      edp 	if (lx_rd == NULL) {
    304  6830      edp 		ps_plog("lx_ldb_init: cannot allocate memory");
    305  2712  nn35248 		return (NULL);
    306  2712  nn35248 	}
    307  6830      edp 	lx_rd->lr_rap = rap;
    308  6830      edp 	lx_rd->lr_php = php;
    309  2712  nn35248 
    310  6830      edp 	phdr_addr = lx_ldb_getauxval32(php, AT_SUN_BRAND_LX_PHDR);
    311  6473      edp 	if (phdr_addr == (uint32_t)-1) {
    312  6830      edp 		ps_plog("lx_ldb_init: no LX_PHDR found in aux vector");
    313  6473      edp 		return (NULL);
    314  6473      edp 	}
    315  6830      edp 	ps_plog("lx_ldb_init: found LX_PHDR auxv phdr at: 0x%p",
    316  6473      edp 	    phdr_addr);
    317  2712  nn35248 
    318  2712  nn35248 	if (ps_pread(php, phdr_addr, &phdr, sizeof (phdr)) != PS_OK) {
    319  6830      edp 		ps_plog("lx_ldb_init: couldn't read phdr at 0x%p",
    320  2712  nn35248 		    phdr_addr);
    321  6830      edp 		free(lx_rd);
    322  2712  nn35248 		return (NULL);
    323  2712  nn35248 	}
    324  2712  nn35248 
    325  6473      edp 	/* The ELF headher should be before the program header in memory */
    326  6830      edp 	lx_rd->lr_exec = addr = phdr_addr - phdr.p_offset;
    327  6830      edp 	if (ps_pread(php, addr, &ehdr, sizeof (ehdr)) != PS_OK) {
    328  6830      edp 		ps_plog("lx_ldb_init: couldn't read ehdr at 0x%p",
    329  6830      edp 		    lx_rd->lr_exec);
    330  6830      edp 		free(lx_rd);
    331  2712  nn35248 		return (NULL);
    332  2712  nn35248 	}
    333  6830      edp 	ps_plog("lx_ldb_init: read ehdr at: 0x%p", addr);
    334  2712  nn35248 
    335  2712  nn35248 	if ((phdrs = malloc(ehdr.e_phnum * ehdr.e_phentsize)) == NULL) {
    336  6830      edp 		ps_plog("lx_ldb_init: couldn't alloc phdrs memory");
    337  6830      edp 		free(lx_rd);
    338  2712  nn35248 		return (NULL);
    339  2712  nn35248 	}
    340  2712  nn35248 
    341  2712  nn35248 	if (ps_pread(php, phdr_addr, phdrs, ehdr.e_phnum * ehdr.e_phentsize) !=
    342  2712  nn35248 	    PS_OK) {
    343  6830      edp 		ps_plog("lx_ldb_init: couldn't read phdrs at 0x%p",
    344  2712  nn35248 		    phdr_addr);
    345  6830      edp 		free(lx_rd);
    346  2712  nn35248 		free(phdrs);
    347  2712  nn35248 		return (NULL);
    348  2712  nn35248 	}
    349  6830      edp 	ps_plog("lx_ldb_init: read %d phdrs at: 0x%p",
    350  6473      edp 	    ehdr.e_phnum, phdr_addr);
    351  2712  nn35248 
    352  2712  nn35248 	for (i = 0, ph = phdrs; i < ehdr.e_phnum; i++,
    353  2712  nn35248 	    /*LINTED */
    354  2712  nn35248 	    ph = (Elf32_Phdr *)((char *)ph + ehdr.e_phentsize)) {
    355  2712  nn35248 		if (ph->p_type == PT_DYNAMIC)
    356  2712  nn35248 			break;
    357  2712  nn35248 	}
    358  2712  nn35248 	if (i == ehdr.e_phnum) {
    359  6830      edp 		ps_plog("lx_ldb_init: no PT_DYNAMIC in executable");
    360  6830      edp 		free(lx_rd);
    361  6473      edp 		free(phdrs);
    362  6473      edp 		return (NULL);
    363  6473      edp 	}
    364  6830      edp 	ps_plog("lx_ldb_init: found PT_DYNAMIC phdr[%d] at: 0x%p",
    365  6473      edp 	    i, (phdr_addr + ((char *)ph - (char *)phdrs)));
    366  6473      edp 
    367  6830      edp 	if ((dyn = malloc(ph->p_filesz)) == NULL) {
    368  6830      edp 		ps_plog("lx_ldb_init: couldn't alloc for PT_DYNAMIC");
    369  6830      edp 		free(lx_rd);
    370  2712  nn35248 		free(phdrs);
    371  2712  nn35248 		return (NULL);
    372  2712  nn35248 	}
    373  2712  nn35248 
    374  6830      edp 	dyn_addr = addr + ph->p_offset;
    375  6830      edp 	dyn_count = ph->p_filesz / sizeof (Elf32_Dyn);
    376  6830      edp 	if (ps_pread(php, dyn_addr, dyn, ph->p_filesz) != PS_OK) {
    377  6830      edp 		ps_plog("lx_ldb_init: couldn't read dynamic at 0x%p",
    378  6830      edp 		    dyn_addr);
    379  6830      edp 		free(lx_rd);
    380  2712  nn35248 		free(phdrs);
    381  6830      edp 		free(dyn);
    382  2712  nn35248 		return (NULL);
    383  2712  nn35248 	}
    384  6830      edp 	ps_plog("lx_ldb_init: read %d dynamic headers at: 0x%p",
    385  6830      edp 	    dyn_count, dyn_addr);
    386  2712  nn35248 
    387  6830      edp 	for (i = 0; i < dyn_count; i++) {
    388  6830      edp 		if (dyn[i].d_tag == DT_DEBUG) {
    389  6830      edp 			lx_rd->lr_rdebug = dyn[i].d_un.d_ptr;
    390  2712  nn35248 			break;
    391  2712  nn35248 		}
    392  2712  nn35248 	}
    393  2712  nn35248 	free(phdrs);
    394  6830      edp 	free(dyn);
    395  2712  nn35248 
    396  6830      edp 	if (lx_rd->lr_rdebug == 0) {
    397  6830      edp 		ps_plog("lx_ldb_init: no DT_DEBUG found in exe");
    398  6830      edp 		free(lx_rd);
    399  2712  nn35248 		return (NULL);
    400  2712  nn35248 	}
    401  6830      edp 	ps_plog("lx_ldb_init: found DT_DEBUG: 0x%p", lx_rd->lr_rdebug);
    402  2712  nn35248 
    403  6830      edp 	return ((rd_helper_data_t)lx_rd);
    404  2712  nn35248 }
    405  2712  nn35248 
    406  2712  nn35248 /*
    407  2712  nn35248  * Given the address of an ELF object in the target, return its size and
    408  2712  nn35248  * the proper link map ID.
    409  2712  nn35248  */
    410  2712  nn35248 static size_t
    411  6830      edp lx_elf_props32(struct ps_prochandle *php, uint32_t addr, psaddr_t *data_addr)
    412  2712  nn35248 {
    413  2712  nn35248 	Elf32_Ehdr	ehdr;
    414  2712  nn35248 	Elf32_Phdr	*phdrs, *ph;
    415  2712  nn35248 	int		i;
    416  6473      edp 	uint32_t	min = (uint32_t)-1;
    417  6473      edp 	uint32_t	max = 0;
    418  2712  nn35248 	size_t		sz;
    419  2712  nn35248 
    420  2712  nn35248 	if (ps_pread(php, addr, &ehdr, sizeof (ehdr)) != PS_OK) {
    421  6473      edp 		ps_plog("lx_elf_props: Couldn't read ELF header at 0x%p",
    422  6473      edp 		    addr);
    423  2712  nn35248 		return (0);
    424  2712  nn35248 	}
    425  2712  nn35248 
    426  2712  nn35248 	if ((phdrs = malloc(ehdr.e_phnum * ehdr.e_phentsize)) == NULL)
    427  2712  nn35248 		return (0);
    428  2712  nn35248 
    429  2712  nn35248 	if (ps_pread(php, addr + ehdr.e_phoff, phdrs, ehdr.e_phnum *
    430  2712  nn35248 	    ehdr.e_phentsize) != PS_OK) {
    431  6473      edp 		ps_plog("lx_elf_props: Couldn't read program headers at 0x%p",
    432  2712  nn35248 		    addr + ehdr.e_phoff);
    433  2712  nn35248 		return (0);
    434  2712  nn35248 	}
    435  2712  nn35248 
    436  2712  nn35248 	for (i = 0, ph = phdrs; i < ehdr.e_phnum; i++,
    437  2712  nn35248 	    /*LINTED */
    438  2712  nn35248 	    ph = (Elf32_Phdr *)((char *)ph + ehdr.e_phentsize)) {
    439  2712  nn35248 
    440  2712  nn35248 		if (ph->p_type != PT_LOAD)
    441  2712  nn35248 			continue;
    442  2712  nn35248 
    443  2712  nn35248 		if ((ph->p_flags & (PF_W | PF_R)) == (PF_W | PF_R)) {
    444  2712  nn35248 			*data_addr = ph->p_vaddr;
    445  2712  nn35248 			if (ehdr.e_type == ET_DYN)
    446  2712  nn35248 				*data_addr += addr;
    447  2712  nn35248 			if (*data_addr & (ph->p_align - 1))
    448  2712  nn35248 				*data_addr = *data_addr & (~(ph->p_align -1));
    449  2712  nn35248 		}
    450  2712  nn35248 
    451  2712  nn35248 		if (ph->p_vaddr < min)
    452  2712  nn35248 			min = ph->p_vaddr;
    453  2712  nn35248 
    454  2712  nn35248 		if (ph->p_vaddr > max) {
    455  2712  nn35248 			max = ph->p_vaddr;
    456  2712  nn35248 			sz = ph->p_memsz + max - min;
    457  2712  nn35248 			if (sz & (ph->p_align - 1))
    458  2712  nn35248 				sz = (sz & (~(ph->p_align - 1))) + ph->p_align;
    459  2712  nn35248 		}
    460  2712  nn35248 	}
    461  2712  nn35248 
    462  2712  nn35248 	free(phdrs);
    463  2712  nn35248 	return (sz);
    464  2712  nn35248 }
    465  2712  nn35248 
    466  2712  nn35248 static int
    467  6830      edp lx_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data)
    468  2712  nn35248 {
    469  6830      edp 	lx_rd_t			*lx_rd = (lx_rd_t *)rhd;
    470  6830      edp 	struct ps_prochandle	*php = lx_rd->lr_php;
    471  6830      edp 	lx_r_debug_t		r_debug;
    472  6830      edp 	lx_link_map_t		map;
    473  6473      edp 	uint32_t		p = NULL;
    474  2712  nn35248 	int			rc;
    475  2712  nn35248 	rd_loadobj_t		exec;
    476  2712  nn35248 
    477  2712  nn35248 	if ((rc = ps_pread(php, (psaddr_t)lx_rd->lr_rdebug, &r_debug,
    478  2712  nn35248 	    sizeof (r_debug))) != PS_OK) {
    479  6830      edp 		ps_plog("lx_ldb_loadobj_iter: "
    480  6830      edp 		    "Couldn't read linux r_debug at 0x%p", lx_rd->lr_rdebug);
    481  2712  nn35248 		return (rc);
    482  2712  nn35248 	}
    483  2712  nn35248 
    484  2712  nn35248 	p = r_debug.r_map;
    485  2712  nn35248 
    486  2712  nn35248 	/*
    487  2712  nn35248 	 * The first item on the link map list is for the executable, but it
    488  2712  nn35248 	 * doesn't give us any useful information about it. We need to
    489  2712  nn35248 	 * synthesize a rd_loadobj_t for the client.
    490  2712  nn35248 	 *
    491  2712  nn35248 	 * Linux doesn't give us the executable name, so we'll get it from
    492  2712  nn35248 	 * the AT_EXECNAME entry instead.
    493  2712  nn35248 	 */
    494  2712  nn35248 	if ((rc = ps_pread(php, (psaddr_t)p, &map, sizeof (map))) != PS_OK) {
    495  6830      edp 		ps_plog("lx_ldb_loadobj_iter: "
    496  6830      edp 		    "Couldn't read linux link map at 0x%p", p);
    497  2712  nn35248 		return (rc);
    498  2712  nn35248 	}
    499  2712  nn35248 
    500  2712  nn35248 	bzero(&exec, sizeof (exec));
    501  2712  nn35248 	exec.rl_base = lx_rd->lr_exec;
    502  2712  nn35248 	exec.rl_dynamic = map.lxm_ld;
    503  6830      edp 	exec.rl_nameaddr = lx_ldb_getauxval32(php, AT_SUN_EXECNAME);
    504  2712  nn35248 	exec.rl_lmident = LM_ID_BASE;
    505  2712  nn35248 
    506  2712  nn35248 	exec.rl_bend = exec.rl_base +
    507  6830      edp 	    lx_elf_props32(php, lx_rd->lr_exec, &exec.rl_data_base);
    508  2712  nn35248 
    509  2712  nn35248 	if ((*cb)(&exec, client_data) == 0) {
    510  6830      edp 		ps_plog("lx_ldb_loadobj_iter: "
    511  6830      edp 		    "client callb failed for executable");
    512  2712  nn35248 		return (PS_ERR);
    513  2712  nn35248 	}
    514  2712  nn35248 
    515  2712  nn35248 	for (p = map.lxm_next; p != NULL; p = map.lxm_next) {
    516  2712  nn35248 		rd_loadobj_t	obj;
    517  2712  nn35248 
    518  2712  nn35248 		if ((rc = ps_pread(php, (psaddr_t)p, &map, sizeof (map))) !=
    519  2712  nn35248 		    PS_OK) {
    520  6830      edp 			ps_plog("lx_ldb_loadobj_iter: "
    521  6830      edp 			    "Couldn't read lk map at %p", p);
    522  2712  nn35248 			return (rc);
    523  2712  nn35248 		}
    524  2712  nn35248 
    525  2712  nn35248 		/*
    526  2712  nn35248 		 * The linux link map has less information than the Solaris one.
    527  2712  nn35248 		 * We need to go fetch the missing information from the ELF
    528  2712  nn35248 		 * headers.
    529  2712  nn35248 		 */
    530  2712  nn35248 
    531  2712  nn35248 		obj.rl_nameaddr = (psaddr_t)map.lxm_name;
    532  2712  nn35248 		obj.rl_base = map.lxm_addr;
    533  2712  nn35248 		obj.rl_refnameaddr = (psaddr_t)map.lxm_name;
    534  2712  nn35248 		obj.rl_plt_base = NULL;
    535  2712  nn35248 		obj.rl_plt_size = 0;
    536  2712  nn35248 		obj.rl_lmident = LM_ID_BASE;
    537  2712  nn35248 
    538  2712  nn35248 		/*
    539  2712  nn35248 		 * Ugh - we have to walk the ELF stuff, find the PT_LOAD
    540  2712  nn35248 		 * sections, and calculate the end of the file's mappings
    541  2712  nn35248 		 * ourselves.
    542  2712  nn35248 		 */
    543  2712  nn35248 
    544  2712  nn35248 		obj.rl_bend = map.lxm_addr +
    545  6830      edp 		    lx_elf_props32(php, map.lxm_addr, &obj.rl_data_base);
    546  2712  nn35248 		obj.rl_padstart = obj.rl_base;
    547  2712  nn35248 		obj.rl_padend = obj.rl_bend;
    548  2712  nn35248 		obj.rl_dynamic = map.lxm_ld;
    549  2712  nn35248 		obj.rl_tlsmodid = 0;
    550  2712  nn35248 
    551  6830      edp 		ps_plog("lx_ldb_loadobj_iter: 0x%p to 0x%p",
    552  6473      edp 		    obj.rl_base, obj.rl_bend);
    553  2712  nn35248 
    554  2712  nn35248 		if ((*cb)(&obj, client_data) == 0) {
    555  6830      edp 			ps_plog("lx_ldb_loadobj_iter: "
    556  6830      edp 			    "Client callback failed on %s", map.lxm_name);
    557  2712  nn35248 			return (rc);
    558  2712  nn35248 		}
    559  2712  nn35248 	}
    560  2712  nn35248 	return (RD_OK);
    561  2712  nn35248 }
    562  6830      edp 
    563  6830      edp /*
    564  6830      edp  * Librtld_db plugin linkage struct.
    565  6830      edp  *
    566  6830      edp  * When we get loaded by librtld_db, it will look for the symbol below
    567  6830      edp  * to find our plugin entry points.
    568  6830      edp  */
    569  6830      edp rd_helper_ops_t RTLD_DB_BRAND_OPS = {
    570  6830      edp 	LM_ID_BRAND,
    571  6830      edp 	lx_ldb_init32,
    572  6830      edp 	lx_ldb_fini32,
    573  6830      edp 	lx_ldb_loadobj_iter32,
    574  6830      edp 	lx_ldb_get_dyns32
    575  6830      edp };
    576