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 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * 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 */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*20c1c355SRod Evans * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257257d1b4Sraf 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Object file dependent support for a.out format objects. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 305aefb655Srie #include <a.out.h> /* Explicitly override M_SEGSIZE */ 315aefb655Srie #include <machdep.h> /* used in M_SROUND */ 325aefb655Srie 3356deab07SRod Evans #include <sys/types.h> 3456deab07SRod Evans #include <sys/procfs.h> 357c478bd9Sstevel@tonic-gate #include <sys/mman.h> 3656deab07SRod Evans #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <unistd.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <limits.h> 407c478bd9Sstevel@tonic-gate #include <stdio.h> 417c478bd9Sstevel@tonic-gate #include <dlfcn.h> 427c478bd9Sstevel@tonic-gate #include <errno.h> 435aefb655Srie #include <debug.h> 447c478bd9Sstevel@tonic-gate #include "_a.out.h" 457c478bd9Sstevel@tonic-gate #include "cache_a.out.h" 467c478bd9Sstevel@tonic-gate #include "msg.h" 477c478bd9Sstevel@tonic-gate #include "_rtld.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * Default and secure dependency search paths. 517c478bd9Sstevel@tonic-gate */ 5256deab07SRod Evans static Spath_defn _aout_def_dirs[] = { 5356deab07SRod Evans { MSG_ORIG(MSG_PTH_USR4LIB), MSG_PTH_USR4LIB_SIZE }, 5456deab07SRod Evans { MSG_ORIG(MSG_PTH_USRLIB), MSG_PTH_USRLIB_SIZE }, 5556deab07SRod Evans { MSG_ORIG(MSG_PTH_USRLCLIB), MSG_PTH_USRLCLIB_SIZE }, 5656deab07SRod Evans { 0, 0 } 577c478bd9Sstevel@tonic-gate }; 587c478bd9Sstevel@tonic-gate 5956deab07SRod Evans static Spath_defn _aout_sec_dirs[] = { 6056deab07SRod Evans { MSG_ORIG(MSG_PTH_LIBSE), MSG_PTH_LIBSE_SIZE }, 6156deab07SRod Evans { 0, 0 } 627c478bd9Sstevel@tonic-gate }; 637c478bd9Sstevel@tonic-gate 6456deab07SRod Evans Alist *aout_def_dirs = NULL; 6556deab07SRod Evans Alist *aout_sec_dirs = NULL; 6656deab07SRod Evans 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * Defines for local functions. 697c478bd9Sstevel@tonic-gate */ 7056deab07SRod Evans static void aout_dladdr(ulong_t, Rt_map *, Dl_info *, void **, int); 7108278a5eSRod Evans static int aout_dlsym_handle(Grp_hdl *, Slookup *, Sresult *, uint_t *, 7208278a5eSRod Evans int *); 7356deab07SRod Evans static Addr aout_entry_point(void); 7408278a5eSRod Evans static int aout_find_sym(Slookup *, Sresult *, uint_t *, int *); 7556deab07SRod Evans static int aout_fix_name(const char *, Rt_map *, Alist **, Aliste, uint_t); 7656deab07SRod Evans static Alist **aout_get_def_dirs(void); 7756deab07SRod Evans static Alist **aout_get_sec_dirs(void); 7856deab07SRod Evans static char *aout_get_so(const char *, const char *, size_t, size_t); 7956deab07SRod Evans static int aout_needed(Lm_list *, Aliste, Rt_map *, int *); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * Functions and data accessed through indirect pointers. 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate Fct aout_fct = { 8556deab07SRod Evans aout_verify, 8656deab07SRod Evans aout_new_lmp, 8756deab07SRod Evans aout_entry_point, 887c478bd9Sstevel@tonic-gate aout_needed, 897c478bd9Sstevel@tonic-gate aout_lookup_sym, 907c478bd9Sstevel@tonic-gate aout_reloc, 9156deab07SRod Evans aout_get_def_dirs, 9256deab07SRod Evans aout_get_sec_dirs, 937c478bd9Sstevel@tonic-gate aout_fix_name, 947c478bd9Sstevel@tonic-gate aout_get_so, 957c478bd9Sstevel@tonic-gate aout_dladdr, 9656deab07SRod Evans aout_dlsym_handle 977c478bd9Sstevel@tonic-gate }; 987c478bd9Sstevel@tonic-gate 9956deab07SRod Evans /* 10056deab07SRod Evans * Default and secure dependency search paths. 10156deab07SRod Evans */ 10256deab07SRod Evans static Alist ** 10356deab07SRod Evans aout_get_def_dirs() 10456deab07SRod Evans { 10556deab07SRod Evans if (aout_def_dirs == NULL) 10656deab07SRod Evans set_dirs(&aout_def_dirs, _aout_def_dirs, LA_SER_DEFAULT); 10756deab07SRod Evans return (&aout_def_dirs); 10856deab07SRod Evans } 10956deab07SRod Evans 11056deab07SRod Evans static Alist ** 11156deab07SRod Evans aout_get_sec_dirs() 11256deab07SRod Evans { 11356deab07SRod Evans if (aout_sec_dirs == NULL) 11456deab07SRod Evans set_dirs(&aout_sec_dirs, _aout_sec_dirs, LA_SER_SECURE); 11556deab07SRod Evans return (&aout_sec_dirs); 11656deab07SRod Evans } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * In 4.x, a needed file or a dlopened file that was a simple file name implied 1207c478bd9Sstevel@tonic-gate * that the file be found in the present working directory. To simulate this 12156deab07SRod Evans * lookup within the ELF rules it is necessary to add a preceding `./' to the 1227c478bd9Sstevel@tonic-gate * filename. 1237c478bd9Sstevel@tonic-gate */ 12456deab07SRod Evans /* ARGSUSED4 */ 12556deab07SRod Evans static int 12656deab07SRod Evans aout_fix_name(const char *oname, Rt_map *clmp, Alist **alpp, Aliste alni, 12756deab07SRod Evans uint_t orig) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate size_t len; 13056deab07SRod Evans Pdesc *pdp; 13156deab07SRod Evans const char *nname; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Check for slash in name, if none, prepend "./", otherwise just 1357c478bd9Sstevel@tonic-gate * return name given. 1367c478bd9Sstevel@tonic-gate */ 13756deab07SRod Evans if (strchr(oname, '/')) { 13856deab07SRod Evans len = strlen(oname) + 1; 13956deab07SRod Evans if ((nname = stravl_insert(oname, 0, len, 0)) == NULL) 14056deab07SRod Evans return (0); 1417c478bd9Sstevel@tonic-gate } else { 14256deab07SRod Evans char buffer[PATH_MAX]; 14356deab07SRod Evans 14456deab07SRod Evans len = strlen(oname) + 3; 14556deab07SRod Evans (void) snprintf(buffer, len, MSG_ORIG(MSG_FMT_4XPATH), oname); 14656deab07SRod Evans if ((nname = stravl_insert(buffer, 0, len, 0)) == NULL) 14756deab07SRod Evans return (0); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 150dde769a2SRod Evans if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc), alni)) == NULL) 1517c478bd9Sstevel@tonic-gate return (0); 15256deab07SRod Evans 15356deab07SRod Evans pdp->pd_pname = nname; 15456deab07SRod Evans pdp->pd_plen = len; 15556deab07SRod Evans pdp->pd_flags = PD_FLG_PNSLASH; 15656deab07SRod Evans 15756deab07SRod Evans DBG_CALL(Dbg_file_fixname(LIST(clmp), nname, oname)); 15856deab07SRod Evans return (1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Determine if we have been given an A_OUT file. Returns 1 if true. 1637c478bd9Sstevel@tonic-gate */ 16456deab07SRod Evans Fct * 16556deab07SRod Evans /* ARGSUSED1 */ 16656deab07SRod Evans aout_verify(caddr_t addr, size_t size, Fdesc *fdp, const char *name, 16756deab07SRod Evans Rej_desc *rej) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate /* LINTED */ 17056deab07SRod Evans struct exec *exec = (struct exec *)addr; 17156deab07SRod Evans 17256deab07SRod Evans if (size < sizeof (exec) || (exec->a_machtype != M_SPARC) || 1737c478bd9Sstevel@tonic-gate (N_BADMAG(*exec))) { 17456deab07SRod Evans return (NULL); 1757c478bd9Sstevel@tonic-gate } 17656deab07SRod Evans return (&aout_fct); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 18056deab07SRod Evans * Return the entry point of the A_OUT executable. Although the entry point 18156deab07SRod Evans * within an ELF file is flexible, the entry point of an A_OUT executable is 18256deab07SRod Evans * always zero. 1837c478bd9Sstevel@tonic-gate */ 18456deab07SRod Evans static Addr 18556deab07SRod Evans aout_entry_point() 1867c478bd9Sstevel@tonic-gate { 1877c478bd9Sstevel@tonic-gate return (0); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Search through the dynamic section for DT_NEEDED entries and perform one 1927c478bd9Sstevel@tonic-gate * of two functions. If only the first argument is specified then load the 1937c478bd9Sstevel@tonic-gate * defined shared object, otherwise add the link map representing the 1947c478bd9Sstevel@tonic-gate * defined link map the the dlopen list. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate static int 1979aa23310Srie aout_needed(Lm_list *lml, Aliste lmco, Rt_map *clmp, int *in_nfavl) 1987c478bd9Sstevel@tonic-gate { 19956deab07SRod Evans Alist *palp = NULL; 2007c478bd9Sstevel@tonic-gate void *need; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate for (need = &TEXTBASE(clmp)[AOUTDYN(clmp)->v2->ld_need]; 2037c478bd9Sstevel@tonic-gate need != &TEXTBASE(clmp)[0]; 2047c478bd9Sstevel@tonic-gate need = &TEXTBASE(clmp)[((Lnk_obj *)(need))->lo_next]) { 2057c478bd9Sstevel@tonic-gate Rt_map *nlmp; 2067c478bd9Sstevel@tonic-gate char *name; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate name = &TEXTBASE(clmp)[((Lnk_obj *)(need))->lo_name]; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (((Lnk_obj *)(need))->lo_library) { 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * If lo_library field is not NULL then this needed 2137c478bd9Sstevel@tonic-gate * library was linked in using the "-l" option. 2147c478bd9Sstevel@tonic-gate * Thus we need to rebuild the library name before 2157c478bd9Sstevel@tonic-gate * trying to load it. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate char *file; 2187c478bd9Sstevel@tonic-gate size_t len; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * Allocate name length plus 20 for full library name. 2227c478bd9Sstevel@tonic-gate * lib.so.. = 7 + (2 * short) + NULL = 7 + 12 + 1 = 20 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate len = strlen(name) + 20; 22556deab07SRod Evans if ((file = malloc(len)) == NULL) 2267c478bd9Sstevel@tonic-gate return (0); 2277c478bd9Sstevel@tonic-gate (void) snprintf(file, len, MSG_ORIG(MSG_FMT_4XLIB), 2287c478bd9Sstevel@tonic-gate name, ((Lnk_obj *)(need))->lo_major, 2297c478bd9Sstevel@tonic-gate ((Lnk_obj *)(need))->lo_minor); 2307c478bd9Sstevel@tonic-gate 2315aefb655Srie DBG_CALL(Dbg_libs_find(lml, file)); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * We need to determine what filename will match the 2357c478bd9Sstevel@tonic-gate * the filename specified (ie, a libc.so.1.2 may match 2367c478bd9Sstevel@tonic-gate * to a libc.so.1.3). It's the real pathname that is 2377c478bd9Sstevel@tonic-gate * recorded in the link maps. If we are presently 2387c478bd9Sstevel@tonic-gate * being traced, skip this pathname generation so 2397c478bd9Sstevel@tonic-gate * that we fall through into load_so() to print the 2407c478bd9Sstevel@tonic-gate * appropriate diagnostics. I don't like this at all. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate if (lml->lm_flags & LML_FLG_TRC_ENABLE) 2437c478bd9Sstevel@tonic-gate name = file; 2447c478bd9Sstevel@tonic-gate else { 24556deab07SRod Evans Spath_desc sd = { search_rules, NULL, 0 }; 24656deab07SRod Evans Pdesc *pdp; 24756deab07SRod Evans char *path = NULL; 2487c478bd9Sstevel@tonic-gate 24956deab07SRod Evans for (pdp = get_next_dir(&sd, clmp, 0); pdp; 25056deab07SRod Evans pdp = get_next_dir(&sd, clmp, 0)) { 251*20c1c355SRod Evans if (pdp->pd_pname == NULL) 2527c478bd9Sstevel@tonic-gate continue; 2537c478bd9Sstevel@tonic-gate 25456deab07SRod Evans if (path = aout_get_so(pdp->pd_pname, 25556deab07SRod Evans file, 0, 0)) 2567c478bd9Sstevel@tonic-gate break; 2577c478bd9Sstevel@tonic-gate } 25856deab07SRod Evans if (path == NULL) { 2595aefb655Srie eprintf(lml, ERR_FATAL, 2607c478bd9Sstevel@tonic-gate MSG_INTL(MSG_SYS_OPEN), file, 2617c478bd9Sstevel@tonic-gate strerror(ENOENT)); 2627c478bd9Sstevel@tonic-gate return (0); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate name = path; 2657c478bd9Sstevel@tonic-gate } 26656deab07SRod Evans if (expand_paths(clmp, name, &palp, 26756deab07SRod Evans AL_CNT_NEEDED, 0, 0) == 0) 2687c478bd9Sstevel@tonic-gate return (0); 2697c478bd9Sstevel@tonic-gate } else { 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * If the library is specified as a pathname, see if 2727c478bd9Sstevel@tonic-gate * it must be fixed to specify the current working 2737c478bd9Sstevel@tonic-gate * directory (ie. libc.so.1.2 -> ./libc.so.1.2). 2747c478bd9Sstevel@tonic-gate */ 27556deab07SRod Evans if (aout_fix_name(name, clmp, &palp, 27656deab07SRod Evans AL_CNT_NEEDED, 0) == 0) 2777c478bd9Sstevel@tonic-gate return (0); 2787c478bd9Sstevel@tonic-gate } 2795aefb655Srie 2805aefb655Srie DBG_CALL(Dbg_file_needed(clmp, name)); 2817c478bd9Sstevel@tonic-gate 28256deab07SRod Evans nlmp = load_one(lml, lmco, palp, clmp, MODE(clmp), 0, 0, 2839aa23310Srie in_nfavl); 2842020b2b6SRod Evans remove_alist(&palp, 1); 285*20c1c355SRod Evans if (((nlmp == NULL) || 286*20c1c355SRod Evans (bind_one(clmp, nlmp, BND_NEEDED) == 0)) && 2877c478bd9Sstevel@tonic-gate ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0)) 2887c478bd9Sstevel@tonic-gate return (0); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate return (1); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate static Sym * 2957c478bd9Sstevel@tonic-gate aout_symconvert(struct nlist *sp) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate static Sym sym; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate sym.st_value = sp->n_value; 3007c478bd9Sstevel@tonic-gate sym.st_size = 0; 3017c478bd9Sstevel@tonic-gate sym.st_info = 0; 3027c478bd9Sstevel@tonic-gate sym.st_other = 0; 3037c478bd9Sstevel@tonic-gate switch (sp->n_type) { 3047c478bd9Sstevel@tonic-gate case N_EXT + N_ABS: 3057c478bd9Sstevel@tonic-gate sym.st_shndx = SHN_ABS; 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate case N_COMM: 3087c478bd9Sstevel@tonic-gate sym.st_shndx = SHN_COMMON; 3097c478bd9Sstevel@tonic-gate break; 3107c478bd9Sstevel@tonic-gate case N_EXT + N_UNDF: 3117c478bd9Sstevel@tonic-gate sym.st_shndx = SHN_UNDEF; 3127c478bd9Sstevel@tonic-gate break; 3137c478bd9Sstevel@tonic-gate default: 3147c478bd9Sstevel@tonic-gate sym.st_shndx = 0; 3157c478bd9Sstevel@tonic-gate break; 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate return (&sym); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Process a.out format commons. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate static struct nlist * 3247c478bd9Sstevel@tonic-gate aout_find_com(struct nlist *sp, const char *name) 3257c478bd9Sstevel@tonic-gate { 326*20c1c355SRod Evans static struct rtc_symb *rtcp = NULL; 3277c478bd9Sstevel@tonic-gate struct rtc_symb *rs, *trs; 3287c478bd9Sstevel@tonic-gate const char *sl; 3297c478bd9Sstevel@tonic-gate char *cp; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * See if common is already allocated. 3337c478bd9Sstevel@tonic-gate */ 3347c478bd9Sstevel@tonic-gate trs = rtcp; 3357c478bd9Sstevel@tonic-gate while (trs) { 3367c478bd9Sstevel@tonic-gate sl = name; 3377c478bd9Sstevel@tonic-gate cp = trs->rtc_sp->n_un.n_name; 3387c478bd9Sstevel@tonic-gate while (*sl == *cp++) 3397c478bd9Sstevel@tonic-gate if (*sl++ == '\0') 3407c478bd9Sstevel@tonic-gate return (trs->rtc_sp); 3417c478bd9Sstevel@tonic-gate trs = trs->rtc_next; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * If we got here, common is not already allocated so allocate it. 3467c478bd9Sstevel@tonic-gate */ 34756deab07SRod Evans if ((rs = malloc(sizeof (struct rtc_symb))) == NULL) 34856deab07SRod Evans return (NULL); 34956deab07SRod Evans if ((rs->rtc_sp = malloc(sizeof (struct nlist))) == NULL) 35056deab07SRod Evans return (NULL); 3517c478bd9Sstevel@tonic-gate trs = rtcp; 3527c478bd9Sstevel@tonic-gate rtcp = rs; 3537c478bd9Sstevel@tonic-gate rs->rtc_next = trs; 3547c478bd9Sstevel@tonic-gate *(rs->rtc_sp) = *sp; 35556deab07SRod Evans if ((rs->rtc_sp->n_un.n_name = malloc(strlen(name) + 1)) == NULL) 35656deab07SRod Evans return (NULL); 3577c478bd9Sstevel@tonic-gate (void) strcpy(rs->rtc_sp->n_un.n_name, name); 3587c478bd9Sstevel@tonic-gate rs->rtc_sp->n_type = N_COMM; 35956deab07SRod Evans if ((rs->rtc_sp->n_value = 36056deab07SRod Evans (long)calloc(rs->rtc_sp->n_value, 1)) == NULL) 36156deab07SRod Evans return (NULL); 3627c478bd9Sstevel@tonic-gate return (rs->rtc_sp); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Find a.out format symbol in the specified link map. Unlike the sister 3677c478bd9Sstevel@tonic-gate * elf routine we re-calculate the symbols hash value for each link map 3687c478bd9Sstevel@tonic-gate * we're looking at. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate static struct nlist * 3717c478bd9Sstevel@tonic-gate aout_findsb(const char *aname, Rt_map *lmp, int flag) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate const char *name = aname; 3747c478bd9Sstevel@tonic-gate char *cp; 3757c478bd9Sstevel@tonic-gate struct fshash *p; 3767c478bd9Sstevel@tonic-gate int i; 3777c478bd9Sstevel@tonic-gate struct nlist *sp; 3787c478bd9Sstevel@tonic-gate ulong_t hval = 0; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate #define HASHMASK 0x7fffffff 3817c478bd9Sstevel@tonic-gate #define RTHS 126 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * The name passed to us is in ELF format, thus it is necessary to 3857c478bd9Sstevel@tonic-gate * map this back to the A_OUT format to compute the hash value (see 3867c478bd9Sstevel@tonic-gate * mapping rules in aout_lookup_sym()). Basically the symbols are 3877c478bd9Sstevel@tonic-gate * mapped according to whether a leading `.' exists. 3887c478bd9Sstevel@tonic-gate * 3897c478bd9Sstevel@tonic-gate * elf symbol a.out symbol 3907c478bd9Sstevel@tonic-gate * i. .bar -> .bar (LKUP_LDOT) 3917c478bd9Sstevel@tonic-gate * ii. .nuts -> nuts 3927c478bd9Sstevel@tonic-gate * iii. foo -> _foo 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate if (*name == '.') { 3957c478bd9Sstevel@tonic-gate if (!(flag & LKUP_LDOT)) 3967c478bd9Sstevel@tonic-gate name++; 3977c478bd9Sstevel@tonic-gate } else 3987c478bd9Sstevel@tonic-gate hval = '_'; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate while (*name) 4017c478bd9Sstevel@tonic-gate hval = (hval << 1) + *name++; 4027c478bd9Sstevel@tonic-gate hval = hval & HASHMASK; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate i = hval % (AOUTDYN(lmp)->v2->ld_buckets == 0 ? RTHS : 4057c478bd9Sstevel@tonic-gate AOUTDYN(lmp)->v2->ld_buckets); 4067c478bd9Sstevel@tonic-gate p = LM2LP(lmp)->lp_hash + i; 4077c478bd9Sstevel@tonic-gate 40856deab07SRod Evans if (p->fssymbno != -1) { 4097c478bd9Sstevel@tonic-gate do { 4107c478bd9Sstevel@tonic-gate sp = &LM2LP(lmp)->lp_symtab[p->fssymbno]; 4117c478bd9Sstevel@tonic-gate cp = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx]; 4127c478bd9Sstevel@tonic-gate name = aname; 4137c478bd9Sstevel@tonic-gate if (*name == '.') { 4147c478bd9Sstevel@tonic-gate if (!(flag & LKUP_LDOT)) 4157c478bd9Sstevel@tonic-gate name++; 4167c478bd9Sstevel@tonic-gate } else { 4177c478bd9Sstevel@tonic-gate cp++; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate while (*name == *cp++) { 4207c478bd9Sstevel@tonic-gate if (*name++ == '\0') 4217c478bd9Sstevel@tonic-gate return (sp); /* found */ 4227c478bd9Sstevel@tonic-gate } 423*20c1c355SRod Evans if (p->next == NULL) 42456deab07SRod Evans return (NULL); /* not found */ 4257c478bd9Sstevel@tonic-gate else 4267c478bd9Sstevel@tonic-gate continue; 427*20c1c355SRod Evans } while ((p = &LM2LP(lmp)->lp_hash[p->next]) != NULL); 42856deab07SRod Evans } 42956deab07SRod Evans return (NULL); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * The symbol name we have been asked to look up is in A_OUT format, this 4347c478bd9Sstevel@tonic-gate * symbol is mapped to the appropriate ELF format which is the standard by 4357c478bd9Sstevel@tonic-gate * which symbols are passed around ld.so.1. The symbols are mapped 4367c478bd9Sstevel@tonic-gate * according to whether a leading `_' or `.' exists. 4377c478bd9Sstevel@tonic-gate * 4387c478bd9Sstevel@tonic-gate * a.out symbol elf symbol 4397c478bd9Sstevel@tonic-gate * i. _foo -> foo 4407c478bd9Sstevel@tonic-gate * ii. .bar -> .bar (LKUP_LDOT) 4417c478bd9Sstevel@tonic-gate * iii. nuts -> .nuts 4427c478bd9Sstevel@tonic-gate */ 44308278a5eSRod Evans int 44408278a5eSRod Evans aout_lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) 4457c478bd9Sstevel@tonic-gate { 4467c478bd9Sstevel@tonic-gate char name[PATH_MAX]; 4477c478bd9Sstevel@tonic-gate Slookup sl = *slp; 4487c478bd9Sstevel@tonic-gate 44956deab07SRod Evans DBG_CALL(Dbg_syms_lookup_aout(LIST(slp->sl_cmap), slp->sl_name)); 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if (*sl.sl_name == '_') 4527c478bd9Sstevel@tonic-gate ++sl.sl_name; 4537c478bd9Sstevel@tonic-gate else if (*sl.sl_name == '.') 4547c478bd9Sstevel@tonic-gate sl.sl_flags |= LKUP_LDOT; 4557c478bd9Sstevel@tonic-gate else { 4567c478bd9Sstevel@tonic-gate name[0] = '.'; 4577c478bd9Sstevel@tonic-gate (void) strcpy(&name[1], sl.sl_name); 4587c478bd9Sstevel@tonic-gate sl.sl_name = name; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * Call the generic lookup routine to cycle through the specified 4637c478bd9Sstevel@tonic-gate * link maps. 4647c478bd9Sstevel@tonic-gate */ 46508278a5eSRod Evans return (lookup_sym(&sl, srp, binfo, in_nfavl)); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * Symbol lookup for an a.out format module. 4707c478bd9Sstevel@tonic-gate */ 4719aa23310Srie /* ARGSUSED3 */ 47208278a5eSRod Evans static int 47308278a5eSRod Evans aout_find_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate const char *name = slp->sl_name; 4767c478bd9Sstevel@tonic-gate Rt_map *ilmp = slp->sl_imap; 4777c478bd9Sstevel@tonic-gate struct nlist *sp; 4787c478bd9Sstevel@tonic-gate 4795aefb655Srie DBG_CALL(Dbg_syms_lookup(ilmp, name, MSG_ORIG(MSG_STR_AOUT))); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate if (sp = aout_findsb(name, ilmp, slp->sl_flags)) { 4827c478bd9Sstevel@tonic-gate if (sp->n_value != 0) { 4837c478bd9Sstevel@tonic-gate /* 4847c478bd9Sstevel@tonic-gate * is it a common? 4857c478bd9Sstevel@tonic-gate */ 4867c478bd9Sstevel@tonic-gate if (sp->n_type == (N_EXT + N_UNDF)) { 487*20c1c355SRod Evans if ((sp = aout_find_com(sp, name)) == NULL) 48808278a5eSRod Evans return (0); 4897c478bd9Sstevel@tonic-gate } 49008278a5eSRod Evans srp->sr_dmap = ilmp; 49108278a5eSRod Evans srp->sr_sym = aout_symconvert(sp); 4927c478bd9Sstevel@tonic-gate *binfo |= DBG_BINFO_FOUND; 49308278a5eSRod Evans return (1); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate } 49608278a5eSRod Evans return (0); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Create a new Rt_map structure for an a.out format object and 5017c478bd9Sstevel@tonic-gate * initializes all values. 5027c478bd9Sstevel@tonic-gate */ 50356deab07SRod Evans /* ARGSUSED6 */ 5047c478bd9Sstevel@tonic-gate Rt_map * 50556deab07SRod Evans aout_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, 5062020b2b6SRod Evans void *odyn, Rt_map *clmp, int *in_nfavl) 5077c478bd9Sstevel@tonic-gate { 50856deab07SRod Evans const char *name = fdp->fd_nname; 5097c478bd9Sstevel@tonic-gate Rt_map *lmp; 51056deab07SRod Evans caddr_t base, caddr = (caddr_t)addr; 51156deab07SRod Evans Link_dynamic *ld = (Link_dynamic *)odyn; 51256deab07SRod Evans size_t lmsz, rtsz, prsz; 5137c478bd9Sstevel@tonic-gate 51456deab07SRod Evans DBG_CALL(Dbg_file_aout(lml, name, addr, msize, lml->lm_lmidstr, lmco)); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * Allocate space for the link-map and private a.out information. Once 5187c478bd9Sstevel@tonic-gate * these are allocated and initialized, we can use remove_so(0, lmp) to 5197c478bd9Sstevel@tonic-gate * tear down the link-map should any failures occur. 5207c478bd9Sstevel@tonic-gate */ 52156deab07SRod Evans rtsz = S_DROUND(sizeof (Rt_map)); 52256deab07SRod Evans prsz = S_DROUND(sizeof (Rt_aoutp)); 52356deab07SRod Evans lmsz = rtsz + prsz + sizeof (struct ld_private); 52456deab07SRod Evans if ((lmp = calloc(lmsz, 1)) == NULL) 52556deab07SRod Evans return (NULL); 52656deab07SRod Evans AOUTPRV(lmp) = (void *)((uintptr_t)lmp + rtsz); 52756deab07SRod Evans ((Rt_aoutp *)AOUTPRV(lmp))->lm_lpd = 52856deab07SRod Evans (void *)((uintptr_t)lmp + rtsz + prsz); 52956deab07SRod Evans LMSIZE(lmp) = lmsz; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * All fields not filled in were set to 0 by calloc. 5337c478bd9Sstevel@tonic-gate */ 53456deab07SRod Evans NAME(lmp) = (char *)name; 53556deab07SRod Evans ADDR(lmp) = addr; 53656deab07SRod Evans MSIZE(lmp) = msize; 5377c478bd9Sstevel@tonic-gate SYMINTP(lmp) = aout_find_sym; 5387c478bd9Sstevel@tonic-gate FCT(lmp) = &aout_fct; 5397c478bd9Sstevel@tonic-gate LIST(lmp) = lml; 5407c478bd9Sstevel@tonic-gate OBJFLTRNDX(lmp) = FLTR_DISABLED; 541dffec89cSrie SORTVAL(lmp) = -1; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate /* 5447c478bd9Sstevel@tonic-gate * Specific settings for a.out format. 5457c478bd9Sstevel@tonic-gate */ 546*20c1c355SRod Evans if (lml->lm_head == NULL) { 54756deab07SRod Evans base = (caddr_t)MAIN_BASE; 5487c478bd9Sstevel@tonic-gate FLAGS(lmp) |= FLG_RT_FIXED; 5497c478bd9Sstevel@tonic-gate } else 55056deab07SRod Evans base = caddr; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 55356deab07SRod Evans * Fill in all AOUT information. Applications provide the Link_dynamic 55456deab07SRod Evans * offset via the boot block, but if this is a shared object that 55556deab07SRod Evans * ld.so.1 has mapped, then determine the Link_dynamic offset from the 55656deab07SRod Evans * mapped image. 5577c478bd9Sstevel@tonic-gate */ 55856deab07SRod Evans if (ld == NULL) { 5597c478bd9Sstevel@tonic-gate /* LINTED */ 56056deab07SRod Evans struct exec *exec = (struct exec *)caddr; 56156deab07SRod Evans struct nlist *nl; 5627c478bd9Sstevel@tonic-gate 56356deab07SRod Evans /* LINTED */ 56456deab07SRod Evans nl = (struct nlist *)&caddr[N_SYMOFF(*exec)]; 56556deab07SRod Evans /* LINTED */ 56656deab07SRod Evans ld = (Link_dynamic *)&caddr[nl->n_value]; 56756deab07SRod Evans 56856deab07SRod Evans ld->v2 = (struct link_dynamic_2 *)((int)ld->v2 + (int)caddr); 56956deab07SRod Evans } 5707c478bd9Sstevel@tonic-gate AOUTDYN(lmp) = ld; 57156deab07SRod Evans 57256deab07SRod Evans if ((RPATH(lmp) = (char *)&base[ld->v2->ld_rules]) == base) 573*20c1c355SRod Evans RPATH(lmp) = NULL; 57456deab07SRod Evans LM2LP(lmp)->lp_symbol_base = caddr; 5757c478bd9Sstevel@tonic-gate /* LINTED */ 57656deab07SRod Evans LM2LP(lmp)->lp_plt = (struct jbind *)(&caddr[JMPOFF(ld)]); 5777c478bd9Sstevel@tonic-gate LM2LP(lmp)->lp_rp = 5787c478bd9Sstevel@tonic-gate /* LINTED */ 57956deab07SRod Evans (struct relocation_info *)(&base[RELOCOFF(ld)]); 5807c478bd9Sstevel@tonic-gate /* LINTED */ 58156deab07SRod Evans LM2LP(lmp)->lp_hash = (struct fshash *)(&base[HASHOFF(ld)]); 5827c478bd9Sstevel@tonic-gate /* LINTED */ 58356deab07SRod Evans LM2LP(lmp)->lp_symtab = (struct nlist *)(&base[SYMOFF(ld)]); 58456deab07SRod Evans LM2LP(lmp)->lp_symstr = &base[STROFF(ld)]; 58556deab07SRod Evans LM2LP(lmp)->lp_textbase = base; 5867c478bd9Sstevel@tonic-gate LM2LP(lmp)->lp_refcnt++; 5877c478bd9Sstevel@tonic-gate LM2LP(lmp)->lp_dlp = NULL; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Add the mapped object to the end of the link map list. 5917c478bd9Sstevel@tonic-gate */ 5927c478bd9Sstevel@tonic-gate lm_append(lml, lmco, lmp); 5937c478bd9Sstevel@tonic-gate return (lmp); 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * Build full pathname of shared object from the given directory name and 5987c478bd9Sstevel@tonic-gate * filename. 5997c478bd9Sstevel@tonic-gate */ 6007c478bd9Sstevel@tonic-gate static char * 60156deab07SRod Evans /* ARGSUSED2 */ 60256deab07SRod Evans aout_get_so(const char *dir, const char *file, size_t dlen, size_t flen) 6037c478bd9Sstevel@tonic-gate { 6047c478bd9Sstevel@tonic-gate struct db *dbp; 6057c478bd9Sstevel@tonic-gate char *path = NULL; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate if (dbp = lo_cache(dir)) { 6087c478bd9Sstevel@tonic-gate path = ask_db(dbp, file); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate return (path); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Determine the symbol location of an address within a link-map. Look for 6157c478bd9Sstevel@tonic-gate * the nearest symbol (whoes value is less than or equal to the required 6167c478bd9Sstevel@tonic-gate * address). This is the object specific part of dladdr(). 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate static void 6197c478bd9Sstevel@tonic-gate aout_dladdr(ulong_t addr, Rt_map *lmp, Dl_info *dlip, void **info, 6207c478bd9Sstevel@tonic-gate int flags) 6217c478bd9Sstevel@tonic-gate { 6227c478bd9Sstevel@tonic-gate ulong_t ndx, cnt, base, _value; 6237c478bd9Sstevel@tonic-gate struct nlist *sym, *_sym; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate cnt = ((int)LM2LP(lmp)->lp_symstr - (int)LM2LP(lmp)->lp_symtab) / 6267c478bd9Sstevel@tonic-gate sizeof (struct nlist); 6277c478bd9Sstevel@tonic-gate sym = LM2LP(lmp)->lp_symtab; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (FLAGS(lmp) & FLG_RT_FIXED) 6307c478bd9Sstevel@tonic-gate base = 0; 6317c478bd9Sstevel@tonic-gate else 6327c478bd9Sstevel@tonic-gate base = ADDR(lmp); 6337c478bd9Sstevel@tonic-gate 634*20c1c355SRod Evans for (_sym = NULL, _value = 0, ndx = 0; ndx < cnt; ndx++, sym++) { 6357c478bd9Sstevel@tonic-gate ulong_t value; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if (sym->n_type == (N_EXT + N_UNDF)) 6387c478bd9Sstevel@tonic-gate continue; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate value = sym->n_value + base; 6417c478bd9Sstevel@tonic-gate if (value > addr) 6427c478bd9Sstevel@tonic-gate continue; 6437c478bd9Sstevel@tonic-gate if (value < _value) 6447c478bd9Sstevel@tonic-gate continue; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate _sym = sym; 6477c478bd9Sstevel@tonic-gate _value = value; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate if (value == addr) 6507c478bd9Sstevel@tonic-gate break; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate if (_sym) { 6547c478bd9Sstevel@tonic-gate int _flags = flags & RTLD_DL_MASK; 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * The only way we can create a symbol entry is to use 6587c478bd9Sstevel@tonic-gate * aout_symconvert(), however this results in us pointing to 6597c478bd9Sstevel@tonic-gate * static data that could be overridden. In addition the AOUT 6607c478bd9Sstevel@tonic-gate * symbol format doesn't give us everything an ELF symbol does. 6617c478bd9Sstevel@tonic-gate * So, unless we get convinced otherwise, don't bother returning 6627c478bd9Sstevel@tonic-gate * a symbol entry for AOUT's. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate if (_flags == RTLD_DL_SYMENT) 665*20c1c355SRod Evans *info = NULL; 6667c478bd9Sstevel@tonic-gate else if (_flags == RTLD_DL_LINKMAP) 6677c478bd9Sstevel@tonic-gate *info = (void *)lmp; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate dlip->dli_sname = &LM2LP(lmp)->lp_symstr[_sym->n_un.n_strx]; 6707c478bd9Sstevel@tonic-gate dlip->dli_saddr = (void *)_value; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Continue processing a dlsym request. Lookup the required symbol in each 6767c478bd9Sstevel@tonic-gate * link-map specified by the handle. Note, that because this lookup is against 6777c478bd9Sstevel@tonic-gate * individual link-maps we don't need to supply a starting link-map to the 6787c478bd9Sstevel@tonic-gate * lookup routine (see lookup_sym():analyze.c). 6797c478bd9Sstevel@tonic-gate */ 68008278a5eSRod Evans static int 68108278a5eSRod Evans aout_dlsym_handle(Grp_hdl *ghp, Slookup *slp, Sresult *srp, uint_t *binfo, 6829aa23310Srie int *in_nfavl) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate char buffer[PATH_MAX]; 6857c478bd9Sstevel@tonic-gate Slookup sl; 6867c478bd9Sstevel@tonic-gate 68708278a5eSRod Evans if (dlsym_handle(ghp, slp, srp, binfo, in_nfavl)) 68808278a5eSRod Evans return (1); 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * Symbol not found as supplied. However, most of our symbols will 6927c478bd9Sstevel@tonic-gate * be in the "C" name space, where the implementation prepends a "_" 6937c478bd9Sstevel@tonic-gate * to the symbol as it emits it. Therefore, attempt to find the 6947c478bd9Sstevel@tonic-gate * symbol with the "_" prepend. 6957c478bd9Sstevel@tonic-gate */ 69608278a5eSRod Evans buffer[0] = '_'; 69708278a5eSRod Evans (void) strcpy(&buffer[1], slp->sl_name); 69808278a5eSRod Evans 6997c478bd9Sstevel@tonic-gate sl = *slp; 7007c478bd9Sstevel@tonic-gate sl.sl_name = (const char *)buffer; 7017c478bd9Sstevel@tonic-gate 70208278a5eSRod Evans return (dlsym_handle(ghp, &sl, srp, binfo, in_nfavl)); 7037c478bd9Sstevel@tonic-gate } 70456deab07SRod Evans 70556deab07SRod Evans /* 70656deab07SRod Evans * The initial mapping of the a.out occurs through exec(2), and presently this 70756deab07SRod Evans * implementation doesn't provide a mmapobj_result_t array to ld.so.1. Thus, 70856deab07SRod Evans * aout_get_mmap() is called to create the mapping information. Unlike ELF, 70956deab07SRod Evans * the information that can be gathered from a mapped AOUT file, can be limited. 71056deab07SRod Evans * In some cases the AOUT header isn't available in the mapped image, and thus 71156deab07SRod Evans * this can't be inspected to determine the files size (the kernel always 71256deab07SRod Evans * returns a pointer to the AOUT dynamic structure, but this is only sufficient 71356deab07SRod Evans * to determine the size of the text segment). 71456deab07SRod Evans * 71556deab07SRod Evans * Therefore, the only generic mechanism of determining the AOUT's mapping is 71656deab07SRod Evans * to use /proc. Only two mappings are required, the text (to determine any 71756deab07SRod Evans * read-only region), and the data. The two mapping validate the range in 71856deab07SRod Evans * which any relocations will occur. Should there be an additional bss segment, 71956deab07SRod Evans * we don't care, as this can't be relocated, and we're never going to try 72056deab07SRod Evans * unmapping the a.out. 72156deab07SRod Evans */ 722*20c1c355SRod Evans #define PROCSIZE 20 723*20c1c355SRod Evans 72456deab07SRod Evans int 72556deab07SRod Evans aout_get_mmap(Lm_list *lml, mmapobj_result_t *mpp) 72656deab07SRod Evans { 72756deab07SRod Evans prmap_t *maps; 728*20c1c355SRod Evans char proc[PROCSIZE]; 72956deab07SRod Evans int num, err, fd; 73056deab07SRod Evans 731*20c1c355SRod Evans (void) snprintf(proc, PROCSIZE, MSG_ORIG(MSG_FMT_PROC), 732*20c1c355SRod Evans EC_SWORD(getpid())); 73356deab07SRod Evans if ((fd = open(proc, O_RDONLY)) == -1) { 73456deab07SRod Evans err = errno; 73556deab07SRod Evans eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), proc, 73656deab07SRod Evans strerror(err)); 73756deab07SRod Evans return (1); 73856deab07SRod Evans } 73956deab07SRod Evans 74056deab07SRod Evans if (ioctl(fd, PIOCNMAP, (void *)&num) == -1) { 74156deab07SRod Evans err = errno; 74256deab07SRod Evans eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), strerror(err)); 74356deab07SRod Evans return (1); 74456deab07SRod Evans } 74556deab07SRod Evans 74656deab07SRod Evans if ((maps = malloc((num + 1) * sizeof (prmap_t))) == NULL) 74756deab07SRod Evans return (1); 74856deab07SRod Evans 74956deab07SRod Evans if (ioctl(fd, PIOCMAP, (void *)maps) == -1) { 75056deab07SRod Evans err = errno; 75156deab07SRod Evans eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_PROC), strerror(err)); 75256deab07SRod Evans free(maps); 75356deab07SRod Evans return (1); 75456deab07SRod Evans } 75556deab07SRod Evans 75656deab07SRod Evans mpp->mr_addr = maps->pr_vaddr; 75756deab07SRod Evans mpp->mr_fsize = mpp->mr_msize = maps->pr_size; 75856deab07SRod Evans mpp->mr_prot = (PROT_READ | PROT_EXEC); 75956deab07SRod Evans 76056deab07SRod Evans mpp++, maps++; 76156deab07SRod Evans 76256deab07SRod Evans mpp->mr_addr = maps->pr_vaddr; 76356deab07SRod Evans mpp->mr_fsize = mpp->mr_msize = maps->pr_size; 76456deab07SRod Evans mpp->mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC); 76556deab07SRod Evans 76656deab07SRod Evans maps--; 76756deab07SRod Evans free(maps); 76856deab07SRod Evans return (0); 76956deab07SRod Evans } 770