xref: /titanic_51/usr/src/cmd/sgs/rtld/common/a.out.c (revision 20c1c3551cb3b3117591ae38463d16aada597c48)
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