xref: /onnv-gate/usr/src/uts/common/krtld/kobj.c (revision 6973:d0d635add03f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51544Seschrock  * Common Development and Distribution License (the "License").
61544Seschrock  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
226206Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Kernel's linker/loader
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/param.h>
340Sstevel@tonic-gate #include <sys/sysmacros.h>
350Sstevel@tonic-gate #include <sys/systm.h>
360Sstevel@tonic-gate #include <sys/user.h>
370Sstevel@tonic-gate #include <sys/kmem.h>
380Sstevel@tonic-gate #include <sys/reboot.h>
390Sstevel@tonic-gate #include <sys/bootconf.h>
400Sstevel@tonic-gate #include <sys/debug.h>
410Sstevel@tonic-gate #include <sys/uio.h>
420Sstevel@tonic-gate #include <sys/file.h>
430Sstevel@tonic-gate #include <sys/vnode.h>
440Sstevel@tonic-gate #include <sys/user.h>
450Sstevel@tonic-gate #include <sys/mman.h>
460Sstevel@tonic-gate #include <vm/as.h>
470Sstevel@tonic-gate #include <vm/seg_kp.h>
480Sstevel@tonic-gate #include <vm/seg_kmem.h>
490Sstevel@tonic-gate #include <sys/elf.h>
500Sstevel@tonic-gate #include <sys/elf_notes.h>
510Sstevel@tonic-gate #include <sys/vmsystm.h>
520Sstevel@tonic-gate #include <sys/kdi.h>
530Sstevel@tonic-gate #include <sys/atomic.h>
540Sstevel@tonic-gate #include <sys/kmdb.h>
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #include <sys/link.h>
570Sstevel@tonic-gate #include <sys/kobj.h>
580Sstevel@tonic-gate #include <sys/ksyms.h>
590Sstevel@tonic-gate #include <sys/disp.h>
600Sstevel@tonic-gate #include <sys/modctl.h>
610Sstevel@tonic-gate #include <sys/varargs.h>
620Sstevel@tonic-gate #include <sys/kstat.h>
630Sstevel@tonic-gate #include <sys/kobj_impl.h>
645648Ssetje #include <sys/fs/decomp.h>
650Sstevel@tonic-gate #include <sys/callb.h>
660Sstevel@tonic-gate #include <sys/cmn_err.h>
670Sstevel@tonic-gate #include <sys/tnf_probe.h>
685648Ssetje #include <sys/zmod.h>
695648Ssetje 
705648Ssetje #include <krtld/reloc.h>
715648Ssetje #include <krtld/kobj_kdi.h>
720Sstevel@tonic-gate #include <sys/sha1.h>
730Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
740Sstevel@tonic-gate 
755648Ssetje #if !defined(_OBP)
760Sstevel@tonic-gate #include <sys/bootvfs.h>
770Sstevel@tonic-gate #endif
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  * do_symbols() error codes
810Sstevel@tonic-gate  */
820Sstevel@tonic-gate #define	DOSYM_UNDEF		-1	/* undefined symbol */
830Sstevel@tonic-gate #define	DOSYM_UNSAFE		-2	/* MT-unsafe driver symbol */
840Sstevel@tonic-gate 
855648Ssetje #if !defined(_OBP)
863446Smrj static void synthetic_bootaux(char *, val_t *);
875648Ssetje #endif
885648Ssetje 
893446Smrj static struct module *load_exec(val_t *, char *);
900Sstevel@tonic-gate static void load_linker(val_t *);
913446Smrj static struct modctl *add_primary(const char *filename, int);
920Sstevel@tonic-gate static int bind_primary(val_t *, int);
930Sstevel@tonic-gate static int load_primary(struct module *, int);
940Sstevel@tonic-gate static int load_kmdb(val_t *);
950Sstevel@tonic-gate static int get_progbits(struct module *, struct _buf *);
960Sstevel@tonic-gate static int get_syms(struct module *, struct _buf *);
970Sstevel@tonic-gate static int get_ctf(struct module *, struct _buf *);
980Sstevel@tonic-gate static void get_signature(struct module *, struct _buf *);
990Sstevel@tonic-gate static int do_common(struct module *);
1000Sstevel@tonic-gate static void add_dependent(struct module *, struct module *);
1010Sstevel@tonic-gate static int do_dependents(struct modctl *, char *, size_t);
1020Sstevel@tonic-gate static int do_symbols(struct module *, Elf64_Addr);
1030Sstevel@tonic-gate static void module_assign(struct modctl *, struct module *);
1040Sstevel@tonic-gate static void free_module_data(struct module *);
1050Sstevel@tonic-gate static char *depends_on(struct module *);
1063446Smrj static char *getmodpath(const char *);
1070Sstevel@tonic-gate static char *basename(char *);
1080Sstevel@tonic-gate static void attr_val(val_t *);
1090Sstevel@tonic-gate static char *find_libmacro(char *);
1100Sstevel@tonic-gate static char *expand_libmacro(char *, char *, char *);
1110Sstevel@tonic-gate static int read_bootflags(void);
1125648Ssetje static int kobj_comp_setup(struct _buf *, struct compinfo *);
1135648Ssetje static int kobj_uncomp_blk(struct _buf *, caddr_t, uint_t);
1145648Ssetje static int kobj_read_blks(struct _buf *, caddr_t, uint_t, uint_t);
1150Sstevel@tonic-gate static int kobj_boot_open(char *, int);
1160Sstevel@tonic-gate static int kobj_boot_close(int);
1170Sstevel@tonic-gate static int kobj_boot_seek(int, off_t, off_t);
1180Sstevel@tonic-gate static int kobj_boot_read(int, caddr_t, size_t);
1191544Seschrock static int kobj_boot_fstat(int, struct bootstat *);
1205648Ssetje static int kobj_boot_compinfo(int, struct compinfo *);
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate static Sym *lookup_one(struct module *, const char *);
1230Sstevel@tonic-gate static void sym_insert(struct module *, char *, symid_t);
1240Sstevel@tonic-gate static Sym *sym_lookup(struct module *, Sym *);
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate static struct kobjopen_tctl *kobjopen_alloc(char *filename);
1270Sstevel@tonic-gate static void kobjopen_free(struct kobjopen_tctl *ltp);
1280Sstevel@tonic-gate static void kobjopen_thread(struct kobjopen_tctl *ltp);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate extern int kcopy(const void *, void *, size_t);
1310Sstevel@tonic-gate extern int elf_mach_ok(Ehdr *);
1320Sstevel@tonic-gate extern int alloc_gottable(struct module *, caddr_t *, caddr_t *);
1330Sstevel@tonic-gate 
1345648Ssetje #if !defined(_OBP)
1355648Ssetje extern int kobj_boot_mountroot(void);
1365648Ssetje #endif
1375648Ssetje 
1385648Ssetje static void tnf_unsplice_probes(uint_t, struct modctl *);
1395648Ssetje extern tnf_probe_control_t *__tnf_probe_list_head;
1405648Ssetje extern tnf_tag_data_t *__tnf_tag_list_head;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate extern int modrootloaded;
1430Sstevel@tonic-gate extern int swaploaded;
1440Sstevel@tonic-gate extern int bop_io_quiesced;
1450Sstevel@tonic-gate extern int last_module_id;
1460Sstevel@tonic-gate 
1475648Ssetje extern char stubs_base[];
1485648Ssetje extern char stubs_end[];
1495648Ssetje 
1500Sstevel@tonic-gate #ifdef KOBJ_DEBUG
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  * Values that can be or'd in to kobj_debug and their effects:
1530Sstevel@tonic-gate  *
1540Sstevel@tonic-gate  *	D_DEBUG		- misc. debugging information.
1550Sstevel@tonic-gate  *	D_SYMBOLS	- list symbols and their values as they are entered
1560Sstevel@tonic-gate  *			  into the hash table
1570Sstevel@tonic-gate  *	D_RELOCATIONS	- display relocation processing information
1580Sstevel@tonic-gate  *	D_LOADING	- display information about each module as it
1590Sstevel@tonic-gate  *			  is loaded.
1600Sstevel@tonic-gate  */
1610Sstevel@tonic-gate int kobj_debug = 0;
1623446Smrj 
1633446Smrj #define	KOBJ_MARK(s)	if (kobj_debug & D_DEBUG)	\
1643446Smrj 	(_kobj_printf(ops, "%d", __LINE__), _kobj_printf(ops, ": %s\n", s))
1653446Smrj #else
1663446Smrj #define	KOBJ_MARK(s)	/* discard */
1670Sstevel@tonic-gate #endif
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate #define	MODPATH_PROPNAME	"module-path"
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
1720Sstevel@tonic-gate static char slash_moddir_suffix_slash[] = MODDIR_SUFFIX "/";
1730Sstevel@tonic-gate #else
1740Sstevel@tonic-gate #define	slash_moddir_suffix_slash	""
1750Sstevel@tonic-gate #endif
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate #define	_moddebug	get_weakish_int(&moddebug)
1780Sstevel@tonic-gate #define	_modrootloaded	get_weakish_int(&modrootloaded)
1790Sstevel@tonic-gate #define	_swaploaded	get_weakish_int(&swaploaded)
1800Sstevel@tonic-gate #define	_ioquiesced	get_weakish_int(&bop_io_quiesced)
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate #define	mod(X)		(struct module *)((X)->modl_modp->mod_mp)
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate void	*romp;		/* rom vector (opaque to us) */
1850Sstevel@tonic-gate struct bootops *ops;	/* bootops vector */
1860Sstevel@tonic-gate void *dbvec;		/* debug vector */
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate  * kobjopen thread control structure
1900Sstevel@tonic-gate  */
1910Sstevel@tonic-gate struct kobjopen_tctl {
1920Sstevel@tonic-gate 	ksema_t		sema;
1930Sstevel@tonic-gate 	char		*name;		/* name of file */
1940Sstevel@tonic-gate 	struct vnode	*vp;		/* vnode return from vn_open() */
1950Sstevel@tonic-gate 	int		Errno;		/* error return from vnopen    */
1960Sstevel@tonic-gate };
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate  * Structure for defining dynamically expandable library macros
2000Sstevel@tonic-gate  */
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate struct lib_macro_info {
2030Sstevel@tonic-gate 	char	*lmi_list;		/* ptr to list of possible choices */
2040Sstevel@tonic-gate 	char	*lmi_macroname;		/* pointer to macro name */
2050Sstevel@tonic-gate 	ushort_t lmi_ba_index;		/* index into bootaux vector */
2060Sstevel@tonic-gate 	ushort_t lmi_macrolen;		/* macro length */
2070Sstevel@tonic-gate } libmacros[] = {
2080Sstevel@tonic-gate 	{ NULL, "CPU", BA_CPU, 0 },
2090Sstevel@tonic-gate 	{ NULL, "MMU", BA_MMU, 0 }
2100Sstevel@tonic-gate };
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate #define	NLIBMACROS	sizeof (libmacros) / sizeof (struct lib_macro_info)
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate char *boot_cpu_compatible_list;			/* make $CPU available */
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 
2173446Smrj char *kobj_module_path;				/* module search path */
2180Sstevel@tonic-gate vmem_t	*text_arena;				/* module text arena */
2190Sstevel@tonic-gate static vmem_t *data_arena;			/* module data & bss arena */
2200Sstevel@tonic-gate static vmem_t *ctf_arena;			/* CTF debug data arena */
2210Sstevel@tonic-gate static struct modctl *kobj_modules = NULL;	/* modules loaded */
2220Sstevel@tonic-gate int kobj_mmu_pagesize;				/* system pagesize */
2230Sstevel@tonic-gate static int lg_pagesize;				/* "large" pagesize */
2240Sstevel@tonic-gate static int kobj_last_module_id = 0;		/* id assignment */
2250Sstevel@tonic-gate static kmutex_t kobj_lock;			/* protects mach memory list */
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate  * The following functions have been implemented by the kernel.
2290Sstevel@tonic-gate  * However, many 3rd party drivers provide their own implementations
2300Sstevel@tonic-gate  * of these functions.  When such drivers are loaded, messages
2315331Samw  * indicating that these symbols have been multiply defined will be
2320Sstevel@tonic-gate  * emitted to the console.  To avoid alarming customers for no good
2330Sstevel@tonic-gate  * reason, we simply suppress such warnings for the following set of
2340Sstevel@tonic-gate  * functions.
2350Sstevel@tonic-gate  */
2360Sstevel@tonic-gate static char *suppress_sym_list[] =
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	"strstr",
2390Sstevel@tonic-gate 	"strncat",
2400Sstevel@tonic-gate 	"strlcat",
2410Sstevel@tonic-gate 	"strlcpy",
2420Sstevel@tonic-gate 	"strspn",
2430Sstevel@tonic-gate 	"memcpy",
2440Sstevel@tonic-gate 	"memset",
2450Sstevel@tonic-gate 	"memmove",
2460Sstevel@tonic-gate 	"memcmp",
2470Sstevel@tonic-gate 	"memchr",
2480Sstevel@tonic-gate 	"__udivdi3",
2490Sstevel@tonic-gate 	"__divdi3",
2500Sstevel@tonic-gate 	"__umoddi3",
2510Sstevel@tonic-gate 	"__moddi3",
2520Sstevel@tonic-gate 	NULL		/* This entry must exist */
2530Sstevel@tonic-gate };
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate /* indexed by KOBJ_NOTIFY_* */
2560Sstevel@tonic-gate static kobj_notify_list_t *kobj_notifiers[KOBJ_NOTIFY_MAX + 1];
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate  * TNF probe management globals
2600Sstevel@tonic-gate  */
2610Sstevel@tonic-gate tnf_probe_control_t	*__tnf_probe_list_head = NULL;
2620Sstevel@tonic-gate tnf_tag_data_t		*__tnf_tag_list_head = NULL;
2630Sstevel@tonic-gate int			tnf_changed_probe_list = 0;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate  * Prefix for statically defined tracing (SDT) DTrace probes.
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate const char		*sdt_prefix = "__dtrace_probe_";
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /*
2713446Smrj  * Beginning and end of the kernel's dynamic text/data segments.
2720Sstevel@tonic-gate  */
2730Sstevel@tonic-gate static caddr_t _text;
2740Sstevel@tonic-gate static caddr_t _etext;
2753446Smrj static caddr_t _data;
2763446Smrj 
2773446Smrj /*
2785648Ssetje  * The sparc linker doesn't create a memory location
2795648Ssetje  * for a variable named _edata, so _edata can only be
2805648Ssetje  * referred to, not modified.  krtld needs a static
2815648Ssetje  * variable to modify it - within krtld, of course -
2825648Ssetje  * outside of krtld, e_data is used in all kernels.
2833446Smrj  */
2845648Ssetje #if defined(__sparc)
2855648Ssetje static caddr_t _edata;
2865648Ssetje #else
2875648Ssetje extern caddr_t _edata;
2883446Smrj #endif
2895648Ssetje 
2905648Ssetje Addr dynseg = 0;	/* load address of "dynamic" segment */
2915648Ssetje size_t dynsize;		/* "dynamic" segment size */
2925648Ssetje 
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate int standalone = 1;			/* an unwholey kernel? */
2950Sstevel@tonic-gate int use_iflush;				/* iflush after relocations */
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate  * _kobj_printf()
2990Sstevel@tonic-gate  *
3000Sstevel@tonic-gate  * Common printf function pointer. Can handle only one conversion
3010Sstevel@tonic-gate  * specification in the format string. Some of the functions invoked
3020Sstevel@tonic-gate  * through this function pointer cannot handle more that one conversion
3030Sstevel@tonic-gate  * specification in the format string.
3040Sstevel@tonic-gate  */
3050Sstevel@tonic-gate void (*_kobj_printf)(void *, const char *, ...);	/* printf routine */
3060Sstevel@tonic-gate 
3075648Ssetje /*
3085648Ssetje  * Standalone function pointers for use within krtld.
3095648Ssetje  * Many platforms implement optimized platmod versions of
3105648Ssetje  * utilities such as bcopy and any such are not yet available
3115648Ssetje  * until the kernel is more completely stitched together.
3125648Ssetje  * See kobj_impl.h
3135648Ssetje  */
3145648Ssetje void (*kobj_bcopy)(const void *, void *, size_t);
3155648Ssetje void (*kobj_bzero)(void *, size_t);
3165648Ssetje size_t (*kobj_strlcat)(char *, const char *, size_t);
3175648Ssetje 
3180Sstevel@tonic-gate static kobj_stat_t kobj_stat;
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate #define	MINALIGN	8	/* at least a double-word */
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate int
3230Sstevel@tonic-gate get_weakish_int(int *ip)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	if (standalone)
3260Sstevel@tonic-gate 		return (0);
3270Sstevel@tonic-gate 	return (ip == NULL ? 0 : *ip);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate static void *
3310Sstevel@tonic-gate get_weakish_pointer(void **ptrp)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate 	if (standalone)
3340Sstevel@tonic-gate 		return (0);
3350Sstevel@tonic-gate 	return (ptrp == NULL ? 0 : *ptrp);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate  * XXX fix dependencies on "kernel"; this should work
3400Sstevel@tonic-gate  * for other standalone binaries as well.
3410Sstevel@tonic-gate  *
3420Sstevel@tonic-gate  * XXX Fix hashing code to use one pointer to
3430Sstevel@tonic-gate  * hash entries.
3440Sstevel@tonic-gate  *	|----------|
3450Sstevel@tonic-gate  *	| nbuckets |
3460Sstevel@tonic-gate  *	|----------|
3470Sstevel@tonic-gate  *	| nchains  |
3480Sstevel@tonic-gate  *	|----------|
3490Sstevel@tonic-gate  *	| bucket[] |
3500Sstevel@tonic-gate  *	|----------|
3510Sstevel@tonic-gate  *	| chain[]  |
3520Sstevel@tonic-gate  *	|----------|
3530Sstevel@tonic-gate  */
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate  * Load, bind and relocate all modules that
3570Sstevel@tonic-gate  * form the primary kernel. At this point, our
3580Sstevel@tonic-gate  * externals have not been relocated.
3590Sstevel@tonic-gate  */
3600Sstevel@tonic-gate void
3610Sstevel@tonic-gate kobj_init(
3620Sstevel@tonic-gate 	void *romvec,
3630Sstevel@tonic-gate 	void *dvec,
3640Sstevel@tonic-gate 	struct bootops *bootvec,
3650Sstevel@tonic-gate 	val_t *bootaux)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate 	struct module *mp;
3680Sstevel@tonic-gate 	struct modctl *modp;
3690Sstevel@tonic-gate 	Addr entry;
3703446Smrj 	char filename[MAXPATHLEN];
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	/*
3730Sstevel@tonic-gate 	 * Save these to pass on to
3740Sstevel@tonic-gate 	 * the booted standalone.
3750Sstevel@tonic-gate 	 */
3760Sstevel@tonic-gate 	romp = romvec;
3770Sstevel@tonic-gate 	dbvec = dvec;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	ops = bootvec;
3805648Ssetje 	kobj_setup_standalone_vectors();
3815648Ssetje 
3823446Smrj 	KOBJ_MARK("Entered kobj_init()");
3830Sstevel@tonic-gate 
3843446Smrj 	(void) BOP_GETPROP(ops, "whoami", filename);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	/*
3870Sstevel@tonic-gate 	 * We don't support standalone debuggers anymore.  The use of kadb
3880Sstevel@tonic-gate 	 * will interfere with the later use of kmdb.  Let the user mend
3890Sstevel@tonic-gate 	 * their ways now.  Users will reach this message if they still
3900Sstevel@tonic-gate 	 * have the kadb binary on their system (perhaps they used an old
3910Sstevel@tonic-gate 	 * bfu, or maybe they intentionally copied it there) and have
3920Sstevel@tonic-gate 	 * specified its use in a way that eluded our checking in the boot
3930Sstevel@tonic-gate 	 * program.
3940Sstevel@tonic-gate 	 */
3950Sstevel@tonic-gate 	if (dvec != NULL) {
3960Sstevel@tonic-gate 		_kobj_printf(ops, "\nWARNING: Standalone debuggers such as "
3970Sstevel@tonic-gate 		    "kadb are no longer supported\n\n");
3980Sstevel@tonic-gate 		goto fail;
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 
4015648Ssetje #if defined(_OBP)
4025648Ssetje 	/*
4035648Ssetje 	 * OBP allows us to read both the ramdisk and
4045648Ssetje 	 * the underlying root fs when root is a disk.
4055648Ssetje 	 * This can lower incidences of unbootable systems
4065648Ssetje 	 * when the archive is out-of-date with the /etc
4075648Ssetje 	 * state files.
4085648Ssetje 	 */
4095648Ssetje 	if (BOP_MOUNTROOT() != BOOT_SVC_OK) {
4105648Ssetje 		_kobj_printf(ops, "can't mount boot fs\n");
4115648Ssetje 		goto fail;
4125648Ssetje 	}
4135648Ssetje #else
4140Sstevel@tonic-gate 	{
4150Sstevel@tonic-gate 		/* on x86, we always boot with a ramdisk */
4160Sstevel@tonic-gate 		(void) kobj_boot_mountroot();
4173446Smrj 
4183446Smrj 		/*
4193446Smrj 		 * Now that the ramdisk is mounted, finish boot property
4203446Smrj 		 * initialization.
4213446Smrj 		 */
4223446Smrj 		boot_prop_finish();
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 
4253446Smrj #if !defined(_UNIX_KRTLD)
4263446Smrj 	/*
4275648Ssetje 	 * 'unix' is linked together with 'krtld' into one executable and
4283446Smrj 	 * the early boot code does -not- hand us any of the dynamic metadata
4293446Smrj 	 * about the executable. In particular, it does not read in, map or
4303446Smrj 	 * otherwise look at the program headers. We fake all that up now.
4313446Smrj 	 *
4323446Smrj 	 * We do this early as DTrace static probes and tnf probes both call
4333446Smrj 	 * undefined references.  We have to process those relocations before
4343446Smrj 	 * calling any of them.
4355648Ssetje 	 *
4365648Ssetje 	 * OBP tells kobj_start() where the ELF image is in memory, so it
4375648Ssetje 	 * synthesized bootaux before kobj_init() was called
4383446Smrj 	 */
4393446Smrj 	if (bootaux[BA_PHDR].ba_ptr == NULL)
4403446Smrj 		synthetic_bootaux(filename, bootaux);
4415648Ssetje 
4425648Ssetje #endif	/* !_UNIX_KRTLD */
4435648Ssetje #endif	/* _OBP */
4443446Smrj 
4453446Smrj 	/*
4463446Smrj 	 * Save the interesting attribute-values
4473446Smrj 	 * (scanned by kobj_boot).
4483446Smrj 	 */
4493446Smrj 	attr_val(bootaux);
4503446Smrj 
4510Sstevel@tonic-gate 	/*
4520Sstevel@tonic-gate 	 * Set the module search path.
4530Sstevel@tonic-gate 	 */
4543446Smrj 	kobj_module_path = getmodpath(filename);
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	boot_cpu_compatible_list = find_libmacro("CPU");
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	/*
4590Sstevel@tonic-gate 	 * These two modules have actually been
4600Sstevel@tonic-gate 	 * loaded by boot, but we finish the job
4610Sstevel@tonic-gate 	 * by introducing them into the world of
4620Sstevel@tonic-gate 	 * loadable modules.
4630Sstevel@tonic-gate 	 */
4640Sstevel@tonic-gate 
4653446Smrj 	mp = load_exec(bootaux, filename);
4660Sstevel@tonic-gate 	load_linker(bootaux);
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	/*
4690Sstevel@tonic-gate 	 * Load all the primary dependent modules.
4700Sstevel@tonic-gate 	 */
4710Sstevel@tonic-gate 	if (load_primary(mp, KOBJ_LM_PRIMARY) == -1)
4720Sstevel@tonic-gate 		goto fail;
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/*
4750Sstevel@tonic-gate 	 * Glue it together.
4760Sstevel@tonic-gate 	 */
4770Sstevel@tonic-gate 	if (bind_primary(bootaux, KOBJ_LM_PRIMARY) == -1)
4780Sstevel@tonic-gate 		goto fail;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	entry = bootaux[BA_ENTRY].ba_val;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/*
4830Sstevel@tonic-gate 	 * Get the boot flags
4840Sstevel@tonic-gate 	 */
4850Sstevel@tonic-gate 	bootflags(ops);
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (boothowto & RB_VERBOSE)
4880Sstevel@tonic-gate 		kobj_lm_dump(KOBJ_LM_PRIMARY);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	kobj_kdi_init();
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	if (boothowto & RB_KMDB) {
4930Sstevel@tonic-gate 		if (load_kmdb(bootaux) < 0)
4940Sstevel@tonic-gate 			goto fail;
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	/*
4980Sstevel@tonic-gate 	 * Post setup.
4990Sstevel@tonic-gate 	 */
5000Sstevel@tonic-gate 	s_text = _text;
5010Sstevel@tonic-gate 	e_text = _etext;
5020Sstevel@tonic-gate 	s_data = _data;
5030Sstevel@tonic-gate 	e_data = _edata;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	kobj_sync_instruction_memory(s_text, e_text - s_text);
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
5080Sstevel@tonic-gate 	if (kobj_debug & D_DEBUG)
5090Sstevel@tonic-gate 		_kobj_printf(ops,
5100Sstevel@tonic-gate 		    "krtld: transferring control to: 0x%p\n", entry);
5110Sstevel@tonic-gate #endif
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	/*
5140Sstevel@tonic-gate 	 * Make sure the mod system knows about the modules already loaded.
5150Sstevel@tonic-gate 	 */
5160Sstevel@tonic-gate 	last_module_id = kobj_last_module_id;
5170Sstevel@tonic-gate 	bcopy(kobj_modules, &modules, sizeof (modules));
5180Sstevel@tonic-gate 	modp = &modules;
5190Sstevel@tonic-gate 	do {
5200Sstevel@tonic-gate 		if (modp->mod_next == kobj_modules)
5210Sstevel@tonic-gate 			modp->mod_next = &modules;
5220Sstevel@tonic-gate 		if (modp->mod_prev == kobj_modules)
5230Sstevel@tonic-gate 			modp->mod_prev = &modules;
5240Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	standalone = 0;
5270Sstevel@tonic-gate 
5285648Ssetje #ifdef	KOBJ_DEBUG
5295648Ssetje 	if (kobj_debug & D_DEBUG)
5305648Ssetje 		_kobj_printf(ops,
5315648Ssetje 		    "krtld: really transferring control to: 0x%p\n", entry);
5325648Ssetje #endif
5335648Ssetje 
5345648Ssetje 	/* restore printf/bcopy/bzero vectors before returning */
5355648Ssetje 	kobj_restore_vectors();
5365648Ssetje 
5375648Ssetje #if defined(_DBOOT)
5380Sstevel@tonic-gate 	/*
5395648Ssetje 	 * krtld was called from a dboot ELF section, the embedded
5405648Ssetje 	 * dboot code contains the real entry via bootaux
5410Sstevel@tonic-gate 	 */
5425648Ssetje 	exitto((caddr_t)entry);
5435648Ssetje #else
5445648Ssetje 	/*
5455648Ssetje 	 * krtld was directly called from startup
5465648Ssetje 	 */
5475648Ssetje 	return;
5480Sstevel@tonic-gate #endif
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate fail:
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	_kobj_printf(ops, "krtld: error during initial load/link phase\n");
5534159Sjosephb 
5544159Sjosephb #if !defined(_UNIX_KRTLD)
5554159Sjosephb 	_kobj_printf(ops, "\n");
5564159Sjosephb 	_kobj_printf(ops, "krtld could neither locate nor resolve symbols"
5574159Sjosephb 	    " for:\n");
5584159Sjosephb 	_kobj_printf(ops, "    %s\n", filename);
5594159Sjosephb 	_kobj_printf(ops, "in the boot archive. Please verify that this"
5604159Sjosephb 	    " file\n");
5614159Sjosephb 	_kobj_printf(ops, "matches what is found in the boot archive.\n");
5624159Sjosephb 	_kobj_printf(ops, "You may need to boot using the Solaris failsafe to"
5634159Sjosephb 	    " fix this.\n");
5644159Sjosephb 	bop_panic("Unable to boot");
5654159Sjosephb #endif
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5685648Ssetje #if !defined(_UNIX_KRTLD) && !defined(_OBP)
5693446Smrj /*
5705648Ssetje  * Synthesize additional metadata that describes the executable if
5715648Ssetje  * krtld's caller didn't do it.
5723446Smrj  *
5733446Smrj  * (When the dynamic executable has an interpreter, the boot program
5743446Smrj  * does all this for us.  Where we don't have an interpreter, (or a
5753446Smrj  * even a boot program, perhaps) we have to do this for ourselves.)
5763446Smrj  */
5773446Smrj static void
5783446Smrj synthetic_bootaux(char *filename, val_t *bootaux)
5793446Smrj {
5803446Smrj 	Ehdr ehdr;
5813446Smrj 	caddr_t phdrbase;
5823446Smrj 	struct _buf *file;
5833446Smrj 	int i, n;
5843446Smrj 
5853446Smrj 	/*
5863446Smrj 	 * Elf header
5873446Smrj 	 */
5883446Smrj 	KOBJ_MARK("synthetic_bootaux()");
5893446Smrj 	KOBJ_MARK(filename);
5903446Smrj 	file = kobj_open_file(filename);
5913446Smrj 	if (file == (struct _buf *)-1) {
5923446Smrj 		_kobj_printf(ops, "krtld: failed to open '%s'\n", filename);
5933446Smrj 		return;
5943446Smrj 	}
5953446Smrj 	KOBJ_MARK("reading program headers");
5963446Smrj 	if (kobj_read_file(file, (char *)&ehdr, sizeof (ehdr), 0) < 0) {
5973446Smrj 		_kobj_printf(ops, "krtld: %s: failed to read ehder\n",
5983446Smrj 		    filename);
5993446Smrj 		return;
6003446Smrj 	}
6013446Smrj 
6023446Smrj 	/*
6033446Smrj 	 * Program headers
6043446Smrj 	 */
6053446Smrj 	bootaux[BA_PHNUM].ba_val = ehdr.e_phnum;
6063446Smrj 	bootaux[BA_PHENT].ba_val = ehdr.e_phentsize;
6073446Smrj 	n = ehdr.e_phentsize * ehdr.e_phnum;
6083446Smrj 
6093446Smrj 	phdrbase = kobj_alloc(n, KM_WAIT | KM_TMP);
6103446Smrj 
6113446Smrj 	if (kobj_read_file(file, phdrbase, n, ehdr.e_phoff) < 0) {
6123446Smrj 		_kobj_printf(ops, "krtld: %s: failed to read phdrs\n",
6133446Smrj 		    filename);
6143446Smrj 		return;
6153446Smrj 	}
6163446Smrj 	bootaux[BA_PHDR].ba_ptr = phdrbase;
6173446Smrj 	kobj_close_file(file);
6183446Smrj 	KOBJ_MARK("closed file");
6193446Smrj 
6203446Smrj 	/*
6213446Smrj 	 * Find the dynamic section address
6223446Smrj 	 */
6233446Smrj 	for (i = 0; i < ehdr.e_phnum; i++) {
6243446Smrj 		Phdr *phdr = (Phdr *)(phdrbase + ehdr.e_phentsize * i);
6253446Smrj 
6263446Smrj 		if (phdr->p_type == PT_DYNAMIC) {
6273446Smrj 			bootaux[BA_DYNAMIC].ba_ptr = (void *)phdr->p_vaddr;
6283446Smrj 			break;
6293446Smrj 		}
6303446Smrj 	}
6313446Smrj 	KOBJ_MARK("synthetic_bootaux() done");
6323446Smrj }
6335648Ssetje #endif	/* !_UNIX_KRTLD && !_OBP */
6343446Smrj 
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate  * Set up any global information derived
6370Sstevel@tonic-gate  * from attribute/values in the boot or
6380Sstevel@tonic-gate  * aux vector.
6390Sstevel@tonic-gate  */
6400Sstevel@tonic-gate static void
6410Sstevel@tonic-gate attr_val(val_t *bootaux)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate 	Phdr *phdr;
6440Sstevel@tonic-gate 	int phnum, phsize;
6450Sstevel@tonic-gate 	int i;
6460Sstevel@tonic-gate 
6473446Smrj 	KOBJ_MARK("attr_val()");
6480Sstevel@tonic-gate 	kobj_mmu_pagesize = bootaux[BA_PAGESZ].ba_val;
6490Sstevel@tonic-gate 	lg_pagesize = bootaux[BA_LPAGESZ].ba_val;
6500Sstevel@tonic-gate 	use_iflush = bootaux[BA_IFLUSH].ba_val;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	phdr = (Phdr *)bootaux[BA_PHDR].ba_ptr;
6530Sstevel@tonic-gate 	phnum = bootaux[BA_PHNUM].ba_val;
6540Sstevel@tonic-gate 	phsize = bootaux[BA_PHENT].ba_val;
6550Sstevel@tonic-gate 	for (i = 0; i < phnum; i++) {
6560Sstevel@tonic-gate 		phdr = (Phdr *)(bootaux[BA_PHDR].ba_val + i * phsize);
6570Sstevel@tonic-gate 
6585648Ssetje 		if (phdr->p_type != PT_LOAD) {
6590Sstevel@tonic-gate 			continue;
6605648Ssetje 		}
6610Sstevel@tonic-gate 		/*
6620Sstevel@tonic-gate 		 * Bounds of the various segments.
6630Sstevel@tonic-gate 		 */
6640Sstevel@tonic-gate 		if (!(phdr->p_flags & PF_X)) {
6655648Ssetje #if defined(_RELSEG)
6665648Ssetje 			/*
6675648Ssetje 			 * sparc kernel puts the dynamic info
6685648Ssetje 			 * into a separate segment, which is
6695648Ssetje 			 * free'd in bop_fini()
6705648Ssetje 			 */
6715648Ssetje 			ASSERT(phdr->p_vaddr != 0);
6720Sstevel@tonic-gate 			dynseg = phdr->p_vaddr;
6735648Ssetje 			dynsize = phdr->p_memsz;
6743446Smrj #else
6753446Smrj 			ASSERT(phdr->p_vaddr == 0);
6763446Smrj #endif
6770Sstevel@tonic-gate 		} else {
6780Sstevel@tonic-gate 			if (phdr->p_flags & PF_W) {
6793446Smrj 				_data = (caddr_t)phdr->p_vaddr;
6803446Smrj 				_edata = _data + phdr->p_memsz;
6810Sstevel@tonic-gate 			} else {
6820Sstevel@tonic-gate 				_text = (caddr_t)phdr->p_vaddr;
6830Sstevel@tonic-gate 				_etext = _text + phdr->p_memsz;
6840Sstevel@tonic-gate 			}
6850Sstevel@tonic-gate 		}
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	/* To do the kobj_alloc, _edata needs to be set. */
6890Sstevel@tonic-gate 	for (i = 0; i < NLIBMACROS; i++) {
6900Sstevel@tonic-gate 		if (bootaux[libmacros[i].lmi_ba_index].ba_ptr != NULL) {
6910Sstevel@tonic-gate 			libmacros[i].lmi_list = kobj_alloc(
6920Sstevel@tonic-gate 			    strlen(bootaux[libmacros[i].lmi_ba_index].ba_ptr) +
6930Sstevel@tonic-gate 			    1, KM_WAIT);
6940Sstevel@tonic-gate 			(void) strcpy(libmacros[i].lmi_list,
6953912Slling 			    bootaux[libmacros[i].lmi_ba_index].ba_ptr);
6960Sstevel@tonic-gate 		}
6970Sstevel@tonic-gate 		libmacros[i].lmi_macrolen = strlen(libmacros[i].lmi_macroname);
6980Sstevel@tonic-gate 	}
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  * Set up the booted executable.
7030Sstevel@tonic-gate  */
7040Sstevel@tonic-gate static struct module *
7053446Smrj load_exec(val_t *bootaux, char *filename)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate 	struct modctl *cp;
7080Sstevel@tonic-gate 	struct module *mp;
7090Sstevel@tonic-gate 	Dyn *dyn;
7100Sstevel@tonic-gate 	Sym *sp;
7110Sstevel@tonic-gate 	int i, lsize, osize, nsize, allocsize;
7120Sstevel@tonic-gate 	char *libname, *tmp;
7135648Ssetje 	char path[MAXPATHLEN];
7143446Smrj 
7153446Smrj #ifdef KOBJ_DEBUG
7163446Smrj 	if (kobj_debug & D_DEBUG)
7173446Smrj 		_kobj_printf(ops, "module path '%s'\n", kobj_module_path);
7183446Smrj #endif
7193446Smrj 
7203446Smrj 	KOBJ_MARK("add_primary");
7210Sstevel@tonic-gate 	cp = add_primary(filename, KOBJ_LM_PRIMARY);
7220Sstevel@tonic-gate 
7233446Smrj 	KOBJ_MARK("struct module");
7240Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
7250Sstevel@tonic-gate 	cp->mod_mp = mp;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	/*
7280Sstevel@tonic-gate 	 * We don't have the following information
7290Sstevel@tonic-gate 	 * since this module is an executable and not
7300Sstevel@tonic-gate 	 * a relocatable .o.
7310Sstevel@tonic-gate 	 */
7320Sstevel@tonic-gate 	mp->symtbl_section = 0;
7330Sstevel@tonic-gate 	mp->shdrs = NULL;
7340Sstevel@tonic-gate 	mp->strhdr = NULL;
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	/*
7370Sstevel@tonic-gate 	 * Since this module is the only exception,
7380Sstevel@tonic-gate 	 * we cons up some section headers.
7390Sstevel@tonic-gate 	 */
7403446Smrj 	KOBJ_MARK("symhdr");
7410Sstevel@tonic-gate 	mp->symhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT);
7423446Smrj 
7433446Smrj 	KOBJ_MARK("strhdr");
7440Sstevel@tonic-gate 	mp->strhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT);
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	mp->symhdr->sh_type = SHT_SYMTAB;
7470Sstevel@tonic-gate 	mp->strhdr->sh_type = SHT_STRTAB;
7480Sstevel@tonic-gate 	/*
7490Sstevel@tonic-gate 	 * Scan the dynamic structure.
7500Sstevel@tonic-gate 	 */
7510Sstevel@tonic-gate 	for (dyn = (Dyn *) bootaux[BA_DYNAMIC].ba_ptr;
7520Sstevel@tonic-gate 	    dyn->d_tag != DT_NULL; dyn++) {
7530Sstevel@tonic-gate 		switch (dyn->d_tag) {
7540Sstevel@tonic-gate 		case DT_SYMTAB:
7550Sstevel@tonic-gate 			mp->symspace = mp->symtbl = (char *)dyn->d_un.d_ptr;
7560Sstevel@tonic-gate 			mp->symhdr->sh_addr = dyn->d_un.d_ptr;
7570Sstevel@tonic-gate 			break;
7580Sstevel@tonic-gate 		case DT_HASH:
7590Sstevel@tonic-gate 			mp->nsyms = *((uint_t *)dyn->d_un.d_ptr + 1);
7600Sstevel@tonic-gate 			mp->hashsize = *(uint_t *)dyn->d_un.d_ptr;
7610Sstevel@tonic-gate 			break;
7620Sstevel@tonic-gate 		case DT_STRTAB:
7630Sstevel@tonic-gate 			mp->strings = (char *)dyn->d_un.d_ptr;
7640Sstevel@tonic-gate 			mp->strhdr->sh_addr = dyn->d_un.d_ptr;
7650Sstevel@tonic-gate 			break;
7660Sstevel@tonic-gate 		case DT_STRSZ:
7670Sstevel@tonic-gate 			mp->strhdr->sh_size = dyn->d_un.d_val;
7680Sstevel@tonic-gate 			break;
7690Sstevel@tonic-gate 		case DT_SYMENT:
7700Sstevel@tonic-gate 			mp->symhdr->sh_entsize = dyn->d_un.d_val;
7710Sstevel@tonic-gate 			break;
7720Sstevel@tonic-gate 		}
7730Sstevel@tonic-gate 	}
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	/*
7760Sstevel@tonic-gate 	 * Collapse any DT_NEEDED entries into one string.
7770Sstevel@tonic-gate 	 */
7780Sstevel@tonic-gate 	nsize = osize = 0;
7790Sstevel@tonic-gate 	allocsize = MAXPATHLEN;
7800Sstevel@tonic-gate 
7813446Smrj 	KOBJ_MARK("depends_on");
7820Sstevel@tonic-gate 	mp->depends_on = kobj_alloc(allocsize, KM_WAIT);
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	for (dyn = (Dyn *) bootaux[BA_DYNAMIC].ba_ptr;
7850Sstevel@tonic-gate 	    dyn->d_tag != DT_NULL; dyn++)
7860Sstevel@tonic-gate 		if (dyn->d_tag == DT_NEEDED) {
7870Sstevel@tonic-gate 			char *_lib;
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 			libname = mp->strings + dyn->d_un.d_val;
7900Sstevel@tonic-gate 			if (strchr(libname, '$') != NULL) {
7910Sstevel@tonic-gate 				if ((_lib = expand_libmacro(libname,
7925648Ssetje 				    path, path)) != NULL)
7930Sstevel@tonic-gate 					libname = _lib;
7940Sstevel@tonic-gate 				else
7950Sstevel@tonic-gate 					_kobj_printf(ops, "krtld: "
7960Sstevel@tonic-gate 					    "load_exec: fail to "
7970Sstevel@tonic-gate 					    "expand %s\n", libname);
7980Sstevel@tonic-gate 			}
7990Sstevel@tonic-gate 			lsize = strlen(libname);
8000Sstevel@tonic-gate 			nsize += lsize;
8010Sstevel@tonic-gate 			if (nsize + 1 > allocsize) {
8023446Smrj 				KOBJ_MARK("grow depends_on");
8030Sstevel@tonic-gate 				tmp = kobj_alloc(allocsize + MAXPATHLEN,
8040Sstevel@tonic-gate 				    KM_WAIT);
8050Sstevel@tonic-gate 				bcopy(mp->depends_on, tmp, osize);
8060Sstevel@tonic-gate 				kobj_free(mp->depends_on, allocsize);
8070Sstevel@tonic-gate 				mp->depends_on = tmp;
8080Sstevel@tonic-gate 				allocsize += MAXPATHLEN;
8090Sstevel@tonic-gate 			}
8100Sstevel@tonic-gate 			bcopy(libname, mp->depends_on + osize, lsize);
8115331Samw 			*(mp->depends_on + nsize) = ' '; /* separate */
8120Sstevel@tonic-gate 			nsize++;
8130Sstevel@tonic-gate 			osize = nsize;
8140Sstevel@tonic-gate 		}
8150Sstevel@tonic-gate 	if (nsize) {
8160Sstevel@tonic-gate 		mp->depends_on[nsize - 1] = '\0'; /* terminate the string */
8170Sstevel@tonic-gate 		/*
8180Sstevel@tonic-gate 		 * alloc with exact size and copy whatever it got over
8190Sstevel@tonic-gate 		 */
8203446Smrj 		KOBJ_MARK("realloc depends_on");
8210Sstevel@tonic-gate 		tmp = kobj_alloc(nsize, KM_WAIT);
8220Sstevel@tonic-gate 		bcopy(mp->depends_on, tmp, nsize);
8230Sstevel@tonic-gate 		kobj_free(mp->depends_on, allocsize);
8240Sstevel@tonic-gate 		mp->depends_on = tmp;
8250Sstevel@tonic-gate 	} else {
8260Sstevel@tonic-gate 		kobj_free(mp->depends_on, allocsize);
8270Sstevel@tonic-gate 		mp->depends_on = NULL;
8280Sstevel@tonic-gate 	}
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	mp->flags = KOBJ_EXEC|KOBJ_PRIM;	/* NOT a relocatable .o */
8310Sstevel@tonic-gate 	mp->symhdr->sh_size = mp->nsyms * mp->symhdr->sh_entsize;
8320Sstevel@tonic-gate 	/*
8330Sstevel@tonic-gate 	 * We allocate our own table since we don't
8340Sstevel@tonic-gate 	 * hash undefined references.
8350Sstevel@tonic-gate 	 */
8363446Smrj 	KOBJ_MARK("chains");
8370Sstevel@tonic-gate 	mp->chains = kobj_zalloc(mp->nsyms * sizeof (symid_t), KM_WAIT);
8383446Smrj 	KOBJ_MARK("buckets");
8390Sstevel@tonic-gate 	mp->buckets = kobj_zalloc(mp->hashsize * sizeof (symid_t), KM_WAIT);
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	mp->text = _text;
8420Sstevel@tonic-gate 	mp->data = _data;
8433446Smrj 
8443446Smrj 	mp->text_size = _etext - _text;
8453446Smrj 	mp->data_size = _edata - _data;
8463446Smrj 
8470Sstevel@tonic-gate 	cp->mod_text = mp->text;
8480Sstevel@tonic-gate 	cp->mod_text_size = mp->text_size;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	mp->filename = cp->mod_filename;
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
8530Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
8540Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
8550Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext: 0x%p", mp->text);
8560Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
8570Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata: 0x%p", mp->data);
8580Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	/*
8630Sstevel@tonic-gate 	 * Insert symbols into the hash table.
8640Sstevel@tonic-gate 	 */
8650Sstevel@tonic-gate 	for (i = 0; i < mp->nsyms; i++) {
8660Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
8690Sstevel@tonic-gate 			continue;
8705648Ssetje #if defined(__sparc)
8710Sstevel@tonic-gate 		/*
8720Sstevel@tonic-gate 		 * Register symbols are ignored in the kernel
8730Sstevel@tonic-gate 		 */
8740Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_SPARC_REGISTER)
8750Sstevel@tonic-gate 			continue;
8760Sstevel@tonic-gate #endif	/* __sparc */
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 		sym_insert(mp, mp->strings + sp->st_name, i);
8790Sstevel@tonic-gate 	}
8800Sstevel@tonic-gate 
8813446Smrj 	KOBJ_MARK("load_exec done");
8820Sstevel@tonic-gate 	return (mp);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate /*
8863446Smrj  * Set up the linker module (if it's compiled in, LDNAME is NULL)
8870Sstevel@tonic-gate  */
8880Sstevel@tonic-gate static void
8890Sstevel@tonic-gate load_linker(val_t *bootaux)
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate 	struct module *kmp = (struct module *)kobj_modules->mod_mp;
8920Sstevel@tonic-gate 	struct module *mp;
8930Sstevel@tonic-gate 	struct modctl *cp;
8940Sstevel@tonic-gate 	int i;
8950Sstevel@tonic-gate 	Shdr *shp;
8960Sstevel@tonic-gate 	Sym *sp;
8970Sstevel@tonic-gate 	int shsize;
8980Sstevel@tonic-gate 	char *dlname = (char *)bootaux[BA_LDNAME].ba_ptr;
8990Sstevel@tonic-gate 
9003446Smrj 	/*
9013446Smrj 	 * On some architectures, krtld is compiled into the kernel.
9023446Smrj 	 */
9033446Smrj 	if (dlname == NULL)
9043446Smrj 		return;
9053446Smrj 
9060Sstevel@tonic-gate 	cp = add_primary(dlname, KOBJ_LM_PRIMARY);
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	cp->mod_mp = mp;
9110Sstevel@tonic-gate 	mp->hdr = *(Ehdr *)bootaux[BA_LDELF].ba_ptr;
9120Sstevel@tonic-gate 	shsize = mp->hdr.e_shentsize * mp->hdr.e_shnum;
9130Sstevel@tonic-gate 	mp->shdrs = kobj_alloc(shsize, KM_WAIT);
9140Sstevel@tonic-gate 	bcopy(bootaux[BA_LDSHDR].ba_ptr, mp->shdrs, shsize);
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	for (i = 1; i < (int)mp->hdr.e_shnum; i++) {
9170Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + (i * mp->hdr.e_shentsize));
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 		if (shp->sh_flags & SHF_ALLOC) {
9200Sstevel@tonic-gate 			if (shp->sh_flags & SHF_WRITE) {
9210Sstevel@tonic-gate 				if (mp->data == NULL)
9220Sstevel@tonic-gate 					mp->data = (char *)shp->sh_addr;
9230Sstevel@tonic-gate 			} else if (mp->text == NULL) {
9240Sstevel@tonic-gate 				mp->text = (char *)shp->sh_addr;
9250Sstevel@tonic-gate 			}
9260Sstevel@tonic-gate 		}
9270Sstevel@tonic-gate 		if (shp->sh_type == SHT_SYMTAB) {
9280Sstevel@tonic-gate 			mp->symtbl_section = i;
9290Sstevel@tonic-gate 			mp->symhdr = shp;
9300Sstevel@tonic-gate 			mp->symspace = mp->symtbl = (char *)shp->sh_addr;
9310Sstevel@tonic-gate 		}
9320Sstevel@tonic-gate 	}
9330Sstevel@tonic-gate 	mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize;
9340Sstevel@tonic-gate 	mp->flags = KOBJ_INTERP|KOBJ_PRIM;
9350Sstevel@tonic-gate 	mp->strhdr = (Shdr *)
9363912Slling 	    (mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize);
9370Sstevel@tonic-gate 	mp->strings = (char *)mp->strhdr->sh_addr;
9380Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	mp->symsize = mp->symhdr->sh_size + mp->strhdr->sh_size + sizeof (int) +
9413912Slling 	    (mp->hashsize + mp->nsyms) * sizeof (symid_t);
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	mp->chains = kobj_zalloc(mp->nsyms * sizeof (symid_t), KM_WAIT);
9440Sstevel@tonic-gate 	mp->buckets = kobj_zalloc(mp->hashsize * sizeof (symid_t), KM_WAIT);
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	mp->bss = bootaux[BA_BSS].ba_val;
9470Sstevel@tonic-gate 	mp->bss_align = 0;	/* pre-aligned during allocation */
9480Sstevel@tonic-gate 	mp->bss_size = (uintptr_t)_edata - mp->bss;
9490Sstevel@tonic-gate 	mp->text_size = _etext - mp->text;
9500Sstevel@tonic-gate 	mp->data_size = _edata - mp->data;
9510Sstevel@tonic-gate 	mp->filename = cp->mod_filename;
9520Sstevel@tonic-gate 	cp->mod_text = mp->text;
9530Sstevel@tonic-gate 	cp->mod_text_size = mp->text_size;
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	/*
9560Sstevel@tonic-gate 	 * Now that we've figured out where the linker is,
9570Sstevel@tonic-gate 	 * set the limits for the booted object.
9580Sstevel@tonic-gate 	 */
9590Sstevel@tonic-gate 	kmp->text_size = (size_t)(mp->text - kmp->text);
9600Sstevel@tonic-gate 	kmp->data_size = (size_t)(mp->data - kmp->data);
9610Sstevel@tonic-gate 	kobj_modules->mod_text_size = kmp->text_size;
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
9640Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
9650Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
9660Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext:0x%p", mp->text);
9670Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
9680Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata:0x%p", mp->data);
9690Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
9700Sstevel@tonic-gate 	}
9710Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 	/*
9740Sstevel@tonic-gate 	 * Insert the symbols into the hash table.
9750Sstevel@tonic-gate 	 */
9760Sstevel@tonic-gate 	for (i = 0; i < mp->nsyms; i++) {
9770Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
9800Sstevel@tonic-gate 			continue;
9810Sstevel@tonic-gate 		if (ELF_ST_BIND(sp->st_info) == STB_GLOBAL) {
9820Sstevel@tonic-gate 			if (sp->st_shndx == SHN_COMMON)
9830Sstevel@tonic-gate 				sp->st_shndx = SHN_ABS;
9840Sstevel@tonic-gate 		}
9850Sstevel@tonic-gate 		sym_insert(mp, mp->strings + sp->st_name, i);
9860Sstevel@tonic-gate 	}
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate static kobj_notify_list_t **
9910Sstevel@tonic-gate kobj_notify_lookup(uint_t type)
9920Sstevel@tonic-gate {
9930Sstevel@tonic-gate 	ASSERT(type != 0 && type < sizeof (kobj_notifiers) /
9940Sstevel@tonic-gate 	    sizeof (kobj_notify_list_t *));
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	return (&kobj_notifiers[type]);
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate int
10000Sstevel@tonic-gate kobj_notify_add(kobj_notify_list_t *knp)
10010Sstevel@tonic-gate {
10020Sstevel@tonic-gate 	kobj_notify_list_t **knl;
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	knl = kobj_notify_lookup(knp->kn_type);
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 	knp->kn_next = NULL;
10070Sstevel@tonic-gate 	knp->kn_prev = NULL;
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	if (*knl != NULL) {
10120Sstevel@tonic-gate 		(*knl)->kn_prev = knp;
10130Sstevel@tonic-gate 		knp->kn_next = *knl;
10140Sstevel@tonic-gate 	}
10150Sstevel@tonic-gate 	(*knl) = knp;
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
10180Sstevel@tonic-gate 	return (0);
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate int
10220Sstevel@tonic-gate kobj_notify_remove(kobj_notify_list_t *knp)
10230Sstevel@tonic-gate {
10240Sstevel@tonic-gate 	kobj_notify_list_t **knl = kobj_notify_lookup(knp->kn_type);
10250Sstevel@tonic-gate 	kobj_notify_list_t *tknp;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	/* LINTED */
10300Sstevel@tonic-gate 	if (tknp = knp->kn_next)
10310Sstevel@tonic-gate 		tknp->kn_prev = knp->kn_prev;
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 	/* LINTED */
10340Sstevel@tonic-gate 	if (tknp = knp->kn_prev)
10350Sstevel@tonic-gate 		tknp->kn_next = knp->kn_next;
10360Sstevel@tonic-gate 	else
10370Sstevel@tonic-gate 		*knl = knp->kn_next;
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 	return (0);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate /*
10450Sstevel@tonic-gate  * Notify all interested callbacks of a specified change in module state.
10460Sstevel@tonic-gate  */
10470Sstevel@tonic-gate static void
10480Sstevel@tonic-gate kobj_notify(int type, struct modctl *modp)
10490Sstevel@tonic-gate {
10500Sstevel@tonic-gate 	kobj_notify_list_t *knp;
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 	if (modp->mod_loadflags & MOD_NONOTIFY || standalone)
10530Sstevel@tonic-gate 		return;
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	for (knp = *(kobj_notify_lookup(type)); knp != NULL; knp = knp->kn_next)
10580Sstevel@tonic-gate 		knp->kn_func(type, modp);
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	/*
10610Sstevel@tonic-gate 	 * KDI notification must be last (it has to allow for work done by the
10620Sstevel@tonic-gate 	 * other notification callbacks), so we call it manually.
10630Sstevel@tonic-gate 	 */
10640Sstevel@tonic-gate 	kobj_kdi_mod_notify(type, modp);
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
10670Sstevel@tonic-gate }
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate /*
10705648Ssetje  * Create the module path.
10710Sstevel@tonic-gate  */
10720Sstevel@tonic-gate static char *
10733446Smrj getmodpath(const char *filename)
10740Sstevel@tonic-gate {
10755648Ssetje 	char *path = kobj_zalloc(MAXPATHLEN, KM_WAIT);
10763446Smrj 
10773446Smrj 	/*
10785648Ssetje 	 * Platform code gets first crack, then add
10795648Ssetje 	 * the default components
10803446Smrj 	 */
10815648Ssetje 	mach_modpath(path, filename);
10825648Ssetje 	if (*path != '\0')
10835648Ssetje 		(void) strcat(path, " ");
10843446Smrj 	return (strcat(path, MOD_DEFPATH));
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate static struct modctl *
10883446Smrj add_primary(const char *filename, int lmid)
10890Sstevel@tonic-gate {
10900Sstevel@tonic-gate 	struct modctl *cp;
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	cp = kobj_zalloc(sizeof (struct modctl), KM_WAIT);
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	cp->mod_filename = kobj_alloc(strlen(filename) + 1, KM_WAIT);
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	/*
10970Sstevel@tonic-gate 	 * For symbol lookup, we assemble our own
10980Sstevel@tonic-gate 	 * modctl list of the primary modules.
10990Sstevel@tonic-gate 	 */
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	(void) strcpy(cp->mod_filename, filename);
11020Sstevel@tonic-gate 	cp->mod_modname = basename(cp->mod_filename);
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 	/* set values for modinfo assuming that the load will work */
11050Sstevel@tonic-gate 	cp->mod_prim = 1;
11060Sstevel@tonic-gate 	cp->mod_loaded = 1;
11070Sstevel@tonic-gate 	cp->mod_installed = 1;
11080Sstevel@tonic-gate 	cp->mod_loadcnt = 1;
11090Sstevel@tonic-gate 	cp->mod_loadflags = MOD_NOAUTOUNLOAD;
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate 	cp->mod_id = kobj_last_module_id++;
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	/*
11140Sstevel@tonic-gate 	 * Link the module in. We'll pass this info on
11150Sstevel@tonic-gate 	 * to the mod squad later.
11160Sstevel@tonic-gate 	 */
11170Sstevel@tonic-gate 	if (kobj_modules == NULL) {
11180Sstevel@tonic-gate 		kobj_modules = cp;
11190Sstevel@tonic-gate 		cp->mod_prev = cp->mod_next = cp;
11200Sstevel@tonic-gate 	} else {
11210Sstevel@tonic-gate 		cp->mod_prev = kobj_modules->mod_prev;
11220Sstevel@tonic-gate 		cp->mod_next = kobj_modules;
11230Sstevel@tonic-gate 		kobj_modules->mod_prev->mod_next = cp;
11240Sstevel@tonic-gate 		kobj_modules->mod_prev = cp;
11250Sstevel@tonic-gate 	}
11260Sstevel@tonic-gate 
11270Sstevel@tonic-gate 	kobj_lm_append(lmid, cp);
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	return (cp);
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate static int
11330Sstevel@tonic-gate bind_primary(val_t *bootaux, int lmid)
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate 	struct modctl_list *linkmap = kobj_lm_lookup(lmid);
11360Sstevel@tonic-gate 	struct modctl_list *lp;
11370Sstevel@tonic-gate 	struct module *mp;
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	/*
11400Sstevel@tonic-gate 	 * Do common symbols.
11410Sstevel@tonic-gate 	 */
11420Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
11430Sstevel@tonic-gate 		mp = mod(lp);
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 		/*
11460Sstevel@tonic-gate 		 * Don't do common section relocations for modules that
11470Sstevel@tonic-gate 		 * don't need it.
11480Sstevel@tonic-gate 		 */
11490Sstevel@tonic-gate 		if (mp->flags & (KOBJ_EXEC|KOBJ_INTERP))
11500Sstevel@tonic-gate 			continue;
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 		if (do_common(mp) < 0)
11530Sstevel@tonic-gate 			return (-1);
11540Sstevel@tonic-gate 	}
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	/*
11570Sstevel@tonic-gate 	 * Resolve symbols.
11580Sstevel@tonic-gate 	 */
11590Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
11600Sstevel@tonic-gate 		mp = mod(lp);
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 		if (do_symbols(mp, 0) < 0)
11630Sstevel@tonic-gate 			return (-1);
11640Sstevel@tonic-gate 	}
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	/*
11670Sstevel@tonic-gate 	 * Do relocations.
11680Sstevel@tonic-gate 	 */
11690Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
11700Sstevel@tonic-gate 		mp = mod(lp);
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC) {
11733446Smrj 			Dyn *dyn;
11743446Smrj 			Word relasz = 0, relaent = 0;
11753446Smrj 			Word shtype;
11763446Smrj 			char *rela = NULL;
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 			for (dyn = (Dyn *)bootaux[BA_DYNAMIC].ba_ptr;
11790Sstevel@tonic-gate 			    dyn->d_tag != DT_NULL; dyn++) {
11800Sstevel@tonic-gate 				switch (dyn->d_tag) {
11810Sstevel@tonic-gate 				case DT_RELASZ:
11820Sstevel@tonic-gate 				case DT_RELSZ:
11830Sstevel@tonic-gate 					relasz = dyn->d_un.d_val;
11840Sstevel@tonic-gate 					break;
11850Sstevel@tonic-gate 				case DT_RELAENT:
11860Sstevel@tonic-gate 				case DT_RELENT:
11870Sstevel@tonic-gate 					relaent = dyn->d_un.d_val;
11880Sstevel@tonic-gate 					break;
11890Sstevel@tonic-gate 				case DT_RELA:
11900Sstevel@tonic-gate 					shtype = SHT_RELA;
11915648Ssetje 					rela = (char *)dyn->d_un.d_ptr;
11920Sstevel@tonic-gate 					break;
11930Sstevel@tonic-gate 				case DT_REL:
11940Sstevel@tonic-gate 					shtype = SHT_REL;
11955648Ssetje 					rela = (char *)dyn->d_un.d_ptr;
11960Sstevel@tonic-gate 					break;
11970Sstevel@tonic-gate 				}
11980Sstevel@tonic-gate 			}
11990Sstevel@tonic-gate 			if (relasz == 0 ||
12000Sstevel@tonic-gate 			    relaent == 0 || rela == NULL) {
12010Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: bind_primary(): "
12020Sstevel@tonic-gate 				    "no relocation information found for "
12030Sstevel@tonic-gate 				    "module %s\n", mp->filename);
12040Sstevel@tonic-gate 				return (-1);
12050Sstevel@tonic-gate 			}
12060Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
12070Sstevel@tonic-gate 			if (kobj_debug & D_RELOCATIONS)
12080Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: relocating: file=%s "
12090Sstevel@tonic-gate 				    "KOBJ_EXEC\n", mp->filename);
12100Sstevel@tonic-gate #endif
12110Sstevel@tonic-gate 			if (do_relocate(mp, rela, shtype, relasz/relaent,
12120Sstevel@tonic-gate 			    relaent, (Addr)mp->text) < 0)
12130Sstevel@tonic-gate 				return (-1);
12140Sstevel@tonic-gate 		} else {
12150Sstevel@tonic-gate 			if (do_relocations(mp) < 0)
12160Sstevel@tonic-gate 				return (-1);
12170Sstevel@tonic-gate 		}
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 		kobj_sync_instruction_memory(mp->text, mp->text_size);
12200Sstevel@tonic-gate 	}
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
12230Sstevel@tonic-gate 		mp = mod(lp);
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 		/*
12260Sstevel@tonic-gate 		 * We need to re-read the full symbol table for the boot file,
12270Sstevel@tonic-gate 		 * since we couldn't use the full one before.  We also need to
12280Sstevel@tonic-gate 		 * load the CTF sections of both the boot file and the
12290Sstevel@tonic-gate 		 * interpreter (us).
12300Sstevel@tonic-gate 		 */
12310Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC) {
12320Sstevel@tonic-gate 			struct _buf *file;
12330Sstevel@tonic-gate 			int n;
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 			file = kobj_open_file(mp->filename);
12360Sstevel@tonic-gate 			if (file == (struct _buf *)-1)
12370Sstevel@tonic-gate 				return (-1);
12380Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)&mp->hdr,
12390Sstevel@tonic-gate 			    sizeof (mp->hdr), 0) < 0)
12400Sstevel@tonic-gate 				return (-1);
12410Sstevel@tonic-gate 			n = mp->hdr.e_shentsize * mp->hdr.e_shnum;
12420Sstevel@tonic-gate 			mp->shdrs = kobj_alloc(n, KM_WAIT);
12430Sstevel@tonic-gate 			if (kobj_read_file(file, mp->shdrs, n,
12440Sstevel@tonic-gate 			    mp->hdr.e_shoff) < 0)
12450Sstevel@tonic-gate 				return (-1);
12460Sstevel@tonic-gate 			if (get_syms(mp, file) < 0)
12470Sstevel@tonic-gate 				return (-1);
12480Sstevel@tonic-gate 			if (get_ctf(mp, file) < 0)
12490Sstevel@tonic-gate 				return (-1);
12500Sstevel@tonic-gate 			kobj_close_file(file);
12510Sstevel@tonic-gate 			mp->flags |= KOBJ_RELOCATED;
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 		} else if (mp->flags & KOBJ_INTERP) {
12540Sstevel@tonic-gate 			struct _buf *file;
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 			/*
12570Sstevel@tonic-gate 			 * The interpreter path fragment in mp->filename
12580Sstevel@tonic-gate 			 * will already have the module directory suffix
12590Sstevel@tonic-gate 			 * in it (if appropriate).
12600Sstevel@tonic-gate 			 */
12610Sstevel@tonic-gate 			file = kobj_open_path(mp->filename, 1, 0);
12620Sstevel@tonic-gate 			if (file == (struct _buf *)-1)
12630Sstevel@tonic-gate 				return (-1);
12640Sstevel@tonic-gate 			if (get_ctf(mp, file) < 0)
12650Sstevel@tonic-gate 				return (-1);
12660Sstevel@tonic-gate 			kobj_close_file(file);
12670Sstevel@tonic-gate 			mp->flags |= KOBJ_RELOCATED;
12680Sstevel@tonic-gate 		}
12690Sstevel@tonic-gate 	}
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate 	return (0);
12720Sstevel@tonic-gate }
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate static struct modctl *
12750Sstevel@tonic-gate mod_already_loaded(char *modname)
12760Sstevel@tonic-gate {
12770Sstevel@tonic-gate 	struct modctl *mctl = kobj_modules;
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	do {
12800Sstevel@tonic-gate 		if (strcmp(modname, mctl->mod_filename) == 0)
12810Sstevel@tonic-gate 			return (mctl);
12820Sstevel@tonic-gate 		mctl = mctl->mod_next;
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	} while (mctl != kobj_modules);
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate 	return (NULL);
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate /*
12900Sstevel@tonic-gate  * Load all the primary dependent modules.
12910Sstevel@tonic-gate  */
12920Sstevel@tonic-gate static int
12930Sstevel@tonic-gate load_primary(struct module *mp, int lmid)
12940Sstevel@tonic-gate {
12950Sstevel@tonic-gate 	struct modctl *cp;
12960Sstevel@tonic-gate 	struct module *dmp;
12970Sstevel@tonic-gate 	char *p, *q;
12980Sstevel@tonic-gate 	char modname[MODMAXNAMELEN];
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 	if ((p = mp->depends_on) == NULL)
13010Sstevel@tonic-gate 		return (0);
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 	/* CONSTANTCONDITION */
13040Sstevel@tonic-gate 	while (1) {
13050Sstevel@tonic-gate 		/*
13060Sstevel@tonic-gate 		 * Skip space.
13070Sstevel@tonic-gate 		 */
13080Sstevel@tonic-gate 		while (*p && (*p == ' ' || *p == '\t'))
13090Sstevel@tonic-gate 			p++;
13100Sstevel@tonic-gate 		/*
13110Sstevel@tonic-gate 		 * Get module name.
13120Sstevel@tonic-gate 		 */
13130Sstevel@tonic-gate 		q = modname;
13140Sstevel@tonic-gate 		while (*p && *p != ' ' && *p != '\t')
13150Sstevel@tonic-gate 			*q++ = *p++;
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 		if (q == modname)
13180Sstevel@tonic-gate 			break;
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 		*q = '\0';
13210Sstevel@tonic-gate 		/*
13220Sstevel@tonic-gate 		 * Check for dup dependencies.
13230Sstevel@tonic-gate 		 */
13240Sstevel@tonic-gate 		if (strcmp(modname, "dtracestubs") == 0 ||
13250Sstevel@tonic-gate 		    mod_already_loaded(modname) != NULL)
13260Sstevel@tonic-gate 			continue;
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate 		cp = add_primary(modname, lmid);
13290Sstevel@tonic-gate 		cp->mod_busy = 1;
13300Sstevel@tonic-gate 		/*
13310Sstevel@tonic-gate 		 * Load it.
13320Sstevel@tonic-gate 		 */
13330Sstevel@tonic-gate 		(void) kobj_load_module(cp, 1);
13340Sstevel@tonic-gate 		cp->mod_busy = 0;
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 		if ((dmp = cp->mod_mp) == NULL) {
13370Sstevel@tonic-gate 			cp->mod_loaded = 0;
13380Sstevel@tonic-gate 			cp->mod_installed = 0;
13390Sstevel@tonic-gate 			cp->mod_loadcnt = 0;
13400Sstevel@tonic-gate 			return (-1);
13410Sstevel@tonic-gate 		}
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 		add_dependent(mp, dmp);
13440Sstevel@tonic-gate 		dmp->flags |= KOBJ_PRIM;
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 		/*
13470Sstevel@tonic-gate 		 * Recurse.
13480Sstevel@tonic-gate 		 */
13490Sstevel@tonic-gate 		if (load_primary(dmp, lmid) == -1) {
13500Sstevel@tonic-gate 			cp->mod_loaded = 0;
13510Sstevel@tonic-gate 			cp->mod_installed = 0;
13520Sstevel@tonic-gate 			cp->mod_loadcnt = 0;
13530Sstevel@tonic-gate 			return (-1);
13540Sstevel@tonic-gate 		}
13550Sstevel@tonic-gate 	}
13560Sstevel@tonic-gate 	return (0);
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate static int
13602191Sszhou console_is_usb_serial(void)
13612191Sszhou {
13622191Sszhou 	char *console;
13632191Sszhou 	int len, ret;
13642191Sszhou 
13652191Sszhou 	if ((len = BOP_GETPROPLEN(ops, "console")) == -1)
13662191Sszhou 		return (0);
13672191Sszhou 
13682191Sszhou 	console = kobj_zalloc(len, KM_WAIT|KM_TMP);
13692191Sszhou 	(void) BOP_GETPROP(ops, "console", console);
13702191Sszhou 	ret = (strcmp(console, "usb-serial") == 0);
13712191Sszhou 	kobj_free(console, len);
13722191Sszhou 
13732191Sszhou 	return (ret);
13742191Sszhou }
13752191Sszhou 
13762191Sszhou static int
13770Sstevel@tonic-gate load_kmdb(val_t *bootaux)
13780Sstevel@tonic-gate {
13790Sstevel@tonic-gate 	struct modctl *mctl;
13800Sstevel@tonic-gate 	struct module *mp;
13810Sstevel@tonic-gate 	Sym *sym;
13820Sstevel@tonic-gate 
13832191Sszhou 	if (console_is_usb_serial()) {
13842191Sszhou 		_kobj_printf(ops, "kmdb not loaded "
13852191Sszhou 		    "(unsupported on usb serial console)\n");
13862191Sszhou 		return (0);
13872191Sszhou 	}
13882191Sszhou 
13890Sstevel@tonic-gate 	_kobj_printf(ops, "Loading kmdb...\n");
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	if ((mctl = add_primary("misc/kmdbmod", KOBJ_LM_DEBUGGER)) == NULL)
13920Sstevel@tonic-gate 		return (-1);
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	mctl->mod_busy = 1;
13950Sstevel@tonic-gate 	(void) kobj_load_module(mctl, 1);
13960Sstevel@tonic-gate 	mctl->mod_busy = 0;
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 	if ((mp = mctl->mod_mp) == NULL)
13990Sstevel@tonic-gate 		return (-1);
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	mp->flags |= KOBJ_PRIM;
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 	if (load_primary(mp, KOBJ_LM_DEBUGGER) < 0)
14040Sstevel@tonic-gate 		return (-1);
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	if (boothowto & RB_VERBOSE)
14070Sstevel@tonic-gate 		kobj_lm_dump(KOBJ_LM_DEBUGGER);
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	if (bind_primary(bootaux, KOBJ_LM_DEBUGGER) < 0)
14100Sstevel@tonic-gate 		return (-1);
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	if ((sym = lookup_one(mctl->mod_mp, "kctl_boot_activate")) == NULL)
14130Sstevel@tonic-gate 		return (-1);
14140Sstevel@tonic-gate 
14153446Smrj #ifdef	KOBJ_DEBUG
14163446Smrj 	if (kobj_debug & D_DEBUG) {
14173446Smrj 		_kobj_printf(ops, "calling kctl_boot_activate() @ 0x%lx\n",
14183446Smrj 		    sym->st_value);
14193446Smrj 		_kobj_printf(ops, "\tops 0x%p\n", ops);
14203446Smrj 		_kobj_printf(ops, "\tromp 0x%p\n", romp);
14213446Smrj 	}
14223446Smrj #endif
14233446Smrj 
14240Sstevel@tonic-gate 	if (((kctl_boot_activate_f *)sym->st_value)(ops, romp, 0,
14250Sstevel@tonic-gate 	    (const char **)kobj_kmdb_argv) < 0)
14260Sstevel@tonic-gate 		return (-1);
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	return (0);
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate /*
14320Sstevel@tonic-gate  * Return a string listing module dependencies.
14330Sstevel@tonic-gate  */
14340Sstevel@tonic-gate static char *
14350Sstevel@tonic-gate depends_on(struct module *mp)
14360Sstevel@tonic-gate {
14370Sstevel@tonic-gate 	Sym *sp;
14380Sstevel@tonic-gate 	char *depstr, *q;
14390Sstevel@tonic-gate 
14400Sstevel@tonic-gate 	/*
14410Sstevel@tonic-gate 	 * The module doesn't have a depends_on value, so let's try it the
14420Sstevel@tonic-gate 	 * old-fashioned way - via "_depends_on"
14430Sstevel@tonic-gate 	 */
14440Sstevel@tonic-gate 	if ((sp = lookup_one(mp, "_depends_on")) == NULL)
14450Sstevel@tonic-gate 		return (NULL);
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 	q = (char *)sp->st_value;
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	/*
14500Sstevel@tonic-gate 	 * Idiot checks. Make sure it's
14510Sstevel@tonic-gate 	 * in-bounds and NULL terminated.
14520Sstevel@tonic-gate 	 */
14530Sstevel@tonic-gate 	if (kobj_addrcheck(mp, q) || q[sp->st_size - 1] != '\0') {
14540Sstevel@tonic-gate 		_kobj_printf(ops, "Error processing dependency for %s\n",
14550Sstevel@tonic-gate 		    mp->filename);
14560Sstevel@tonic-gate 		return (NULL);
14570Sstevel@tonic-gate 	}
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 	depstr = (char *)kobj_alloc(strlen(q) + 1, KM_WAIT);
14600Sstevel@tonic-gate 	(void) strcpy(depstr, q);
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 	return (depstr);
14630Sstevel@tonic-gate }
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate void
14660Sstevel@tonic-gate kobj_getmodinfo(void *xmp, struct modinfo *modinfo)
14670Sstevel@tonic-gate {
14680Sstevel@tonic-gate 	struct module *mp;
14690Sstevel@tonic-gate 	mp = (struct module *)xmp;
14700Sstevel@tonic-gate 
14710Sstevel@tonic-gate 	modinfo->mi_base = mp->text;
14720Sstevel@tonic-gate 	modinfo->mi_size = mp->text_size + mp->data_size;
14730Sstevel@tonic-gate }
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate /*
14760Sstevel@tonic-gate  * kobj_export_ksyms() performs the following services:
14770Sstevel@tonic-gate  *
14780Sstevel@tonic-gate  * (1) Migrates the symbol table from boot/kobj memory to the ksyms arena.
14790Sstevel@tonic-gate  * (2) Removes unneeded symbols to save space.
14800Sstevel@tonic-gate  * (3) Reduces memory footprint by using VM_BESTFIT allocations.
14810Sstevel@tonic-gate  * (4) Makes the symbol table visible to /dev/ksyms.
14820Sstevel@tonic-gate  */
14830Sstevel@tonic-gate static void
14840Sstevel@tonic-gate kobj_export_ksyms(struct module *mp)
14850Sstevel@tonic-gate {
14860Sstevel@tonic-gate 	Sym *esp = (Sym *)(mp->symtbl + mp->symhdr->sh_size);
14870Sstevel@tonic-gate 	Sym *sp, *osp;
14880Sstevel@tonic-gate 	char *name;
14890Sstevel@tonic-gate 	size_t namelen;
14900Sstevel@tonic-gate 	struct module *omp;
14910Sstevel@tonic-gate 	uint_t nsyms;
14920Sstevel@tonic-gate 	size_t symsize = mp->symhdr->sh_entsize;
14930Sstevel@tonic-gate 	size_t locals = 1;
14940Sstevel@tonic-gate 	size_t strsize;
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate 	/*
14970Sstevel@tonic-gate 	 * Make a copy of the original module structure.
14980Sstevel@tonic-gate 	 */
14990Sstevel@tonic-gate 	omp = kobj_alloc(sizeof (struct module), KM_WAIT);
15000Sstevel@tonic-gate 	bcopy(mp, omp, sizeof (struct module));
15010Sstevel@tonic-gate 
15020Sstevel@tonic-gate 	/*
15030Sstevel@tonic-gate 	 * Compute the sizes of the new symbol table sections.
15040Sstevel@tonic-gate 	 */
15050Sstevel@tonic-gate 	for (nsyms = strsize = 1, osp = (Sym *)omp->symtbl; osp < esp; osp++) {
15060Sstevel@tonic-gate 		if (osp->st_value == 0)
15070Sstevel@tonic-gate 			continue;
15080Sstevel@tonic-gate 		if (sym_lookup(omp, osp) == NULL)
15090Sstevel@tonic-gate 			continue;
15100Sstevel@tonic-gate 		name = omp->strings + osp->st_name;
15110Sstevel@tonic-gate 		namelen = strlen(name);
15120Sstevel@tonic-gate 		if (ELF_ST_BIND(osp->st_info) == STB_LOCAL)
15130Sstevel@tonic-gate 			locals++;
15140Sstevel@tonic-gate 		nsyms++;
15150Sstevel@tonic-gate 		strsize += namelen + 1;
15160Sstevel@tonic-gate 	}
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate 	mp->nsyms = nsyms;
15190Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate 	/*
15220Sstevel@tonic-gate 	 * ksyms_lock must be held as writer during any operation that
15230Sstevel@tonic-gate 	 * modifies ksyms_arena, including allocation from same, and
15240Sstevel@tonic-gate 	 * must not be dropped until the arena is vmem_walk()able.
15250Sstevel@tonic-gate 	 */
15260Sstevel@tonic-gate 	rw_enter(&ksyms_lock, RW_WRITER);
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 	/*
15290Sstevel@tonic-gate 	 * Allocate space for the new section headers (symtab and strtab),
15300Sstevel@tonic-gate 	 * symbol table, buckets, chains, and strings.
15310Sstevel@tonic-gate 	 */
15320Sstevel@tonic-gate 	mp->symsize = (2 * sizeof (Shdr)) + (nsyms * symsize) +
15330Sstevel@tonic-gate 	    (mp->hashsize + mp->nsyms) * sizeof (symid_t) + strsize;
15340Sstevel@tonic-gate 
15350Sstevel@tonic-gate 	if (mp->flags & KOBJ_NOKSYMS) {
15360Sstevel@tonic-gate 		mp->symspace = kobj_alloc(mp->symsize, KM_WAIT);
15370Sstevel@tonic-gate 	} else {
15380Sstevel@tonic-gate 		mp->symspace = vmem_alloc(ksyms_arena, mp->symsize,
15390Sstevel@tonic-gate 		    VM_BESTFIT | VM_SLEEP);
15400Sstevel@tonic-gate 	}
15410Sstevel@tonic-gate 	bzero(mp->symspace, mp->symsize);
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate 	/*
15440Sstevel@tonic-gate 	 * Divvy up symspace.
15450Sstevel@tonic-gate 	 */
15460Sstevel@tonic-gate 	mp->shdrs = mp->symspace;
15470Sstevel@tonic-gate 	mp->symhdr = (Shdr *)mp->shdrs;
15480Sstevel@tonic-gate 	mp->strhdr = (Shdr *)(mp->symhdr + 1);
15490Sstevel@tonic-gate 	mp->symtbl = (char *)(mp->strhdr + 1);
15500Sstevel@tonic-gate 	mp->buckets = (symid_t *)(mp->symtbl + (nsyms * symsize));
15510Sstevel@tonic-gate 	mp->chains = (symid_t *)(mp->buckets + mp->hashsize);
15520Sstevel@tonic-gate 	mp->strings = (char *)(mp->chains + nsyms);
15530Sstevel@tonic-gate 
15540Sstevel@tonic-gate 	/*
15550Sstevel@tonic-gate 	 * Fill in the new section headers (symtab and strtab).
15560Sstevel@tonic-gate 	 */
15570Sstevel@tonic-gate 	mp->hdr.e_shnum = 2;
15580Sstevel@tonic-gate 	mp->symtbl_section = 0;
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	mp->symhdr->sh_type = SHT_SYMTAB;
15610Sstevel@tonic-gate 	mp->symhdr->sh_addr = (Addr)mp->symtbl;
15620Sstevel@tonic-gate 	mp->symhdr->sh_size = nsyms * symsize;
15630Sstevel@tonic-gate 	mp->symhdr->sh_link = 1;
15640Sstevel@tonic-gate 	mp->symhdr->sh_info = locals;
15650Sstevel@tonic-gate 	mp->symhdr->sh_addralign = sizeof (Addr);
15660Sstevel@tonic-gate 	mp->symhdr->sh_entsize = symsize;
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 	mp->strhdr->sh_type = SHT_STRTAB;
15690Sstevel@tonic-gate 	mp->strhdr->sh_addr = (Addr)mp->strings;
15700Sstevel@tonic-gate 	mp->strhdr->sh_size = strsize;
15710Sstevel@tonic-gate 	mp->strhdr->sh_addralign = 1;
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	/*
15740Sstevel@tonic-gate 	 * Construct the new symbol table.
15750Sstevel@tonic-gate 	 */
15760Sstevel@tonic-gate 	for (nsyms = strsize = 1, osp = (Sym *)omp->symtbl; osp < esp; osp++) {
15770Sstevel@tonic-gate 		if (osp->st_value == 0)
15780Sstevel@tonic-gate 			continue;
15790Sstevel@tonic-gate 		if (sym_lookup(omp, osp) == NULL)
15800Sstevel@tonic-gate 			continue;
15810Sstevel@tonic-gate 		name = omp->strings + osp->st_name;
15820Sstevel@tonic-gate 		namelen = strlen(name);
15830Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + symsize * nsyms);
15840Sstevel@tonic-gate 		bcopy(osp, sp, symsize);
15850Sstevel@tonic-gate 		bcopy(name, mp->strings + strsize, namelen);
15860Sstevel@tonic-gate 		sp->st_name = strsize;
15870Sstevel@tonic-gate 		sym_insert(mp, name, nsyms);
15880Sstevel@tonic-gate 		nsyms++;
15890Sstevel@tonic-gate 		strsize += namelen + 1;
15900Sstevel@tonic-gate 	}
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 	rw_exit(&ksyms_lock);
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 	/*
15950Sstevel@tonic-gate 	 * Free the old section headers -- we'll never need them again.
15960Sstevel@tonic-gate 	 */
15974515Skchow 	if (!(mp->flags & KOBJ_PRIM)) {
15984515Skchow 		uint_t	shn;
15994515Skchow 		Shdr	*shp;
16004515Skchow 
16014515Skchow 		for (shn = 1; shn < omp->hdr.e_shnum; shn++) {
16024515Skchow 			shp = (Shdr *)(omp->shdrs + shn * omp->hdr.e_shentsize);
16034515Skchow 			switch (shp->sh_type) {
16044515Skchow 			case SHT_RELA:
16054515Skchow 			case SHT_REL:
16064515Skchow 				if (shp->sh_addr != 0) {
16074515Skchow 					kobj_free((void *)shp->sh_addr,
16084515Skchow 					    shp->sh_size);
16094515Skchow 				}
16104515Skchow 				break;
16114515Skchow 			}
16124515Skchow 		}
16130Sstevel@tonic-gate 		kobj_free(omp->shdrs, omp->hdr.e_shentsize * omp->hdr.e_shnum);
16144515Skchow 	}
16150Sstevel@tonic-gate 	/*
16160Sstevel@tonic-gate 	 * Discard the old symbol table and our copy of the module strucure.
16170Sstevel@tonic-gate 	 */
16180Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_PRIM))
16190Sstevel@tonic-gate 		kobj_free(omp->symspace, omp->symsize);
16200Sstevel@tonic-gate 	kobj_free(omp, sizeof (struct module));
16210Sstevel@tonic-gate }
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate static void
16240Sstevel@tonic-gate kobj_export_ctf(struct module *mp)
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate 	char *data = mp->ctfdata;
16270Sstevel@tonic-gate 	size_t size = mp->ctfsize;
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 	if (data != NULL) {
16300Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_NOCTF) {
16310Sstevel@tonic-gate 			mp->ctfdata = NULL;
16320Sstevel@tonic-gate 			mp->ctfsize = 0;
16330Sstevel@tonic-gate 		} else {
16340Sstevel@tonic-gate 			mp->ctfdata = vmem_alloc(ctf_arena, size,
16350Sstevel@tonic-gate 			    VM_BESTFIT | VM_SLEEP);
16360Sstevel@tonic-gate 			bcopy(data, mp->ctfdata, size);
16370Sstevel@tonic-gate 		}
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_PRIM))
16400Sstevel@tonic-gate 			kobj_free(data, size);
16410Sstevel@tonic-gate 	}
16420Sstevel@tonic-gate }
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate void
16450Sstevel@tonic-gate kobj_export_module(struct module *mp)
16460Sstevel@tonic-gate {
16470Sstevel@tonic-gate 	kobj_export_ksyms(mp);
16480Sstevel@tonic-gate 	kobj_export_ctf(mp);
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	mp->flags |= KOBJ_EXPORTED;
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate static int
16540Sstevel@tonic-gate process_dynamic(struct module *mp, char *dyndata, char *strdata)
16550Sstevel@tonic-gate {
16560Sstevel@tonic-gate 	char *path = NULL, *depstr = NULL;
16570Sstevel@tonic-gate 	int allocsize = 0, osize = 0, nsize = 0;
16580Sstevel@tonic-gate 	char *libname, *tmp;
16590Sstevel@tonic-gate 	int lsize;
16600Sstevel@tonic-gate 	Dyn *dynp;
16610Sstevel@tonic-gate 
16620Sstevel@tonic-gate 	for (dynp = (Dyn *)dyndata; dynp && dynp->d_tag != DT_NULL; dynp++) {
16630Sstevel@tonic-gate 		switch (dynp->d_tag) {
16640Sstevel@tonic-gate 		case DT_NEEDED:
16650Sstevel@tonic-gate 			/*
16660Sstevel@tonic-gate 			 * Read the DT_NEEDED entries, expanding the macros they
16670Sstevel@tonic-gate 			 * contain (if any), and concatenating them into a
16680Sstevel@tonic-gate 			 * single space-separated dependency list.
16690Sstevel@tonic-gate 			 */
16700Sstevel@tonic-gate 			libname = (ulong_t)dynp->d_un.d_ptr + strdata;
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 			if (strchr(libname, '$') != NULL) {
16730Sstevel@tonic-gate 				char *_lib;
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 				if (path == NULL)
16760Sstevel@tonic-gate 					path = kobj_alloc(MAXPATHLEN, KM_WAIT);
16770Sstevel@tonic-gate 				if ((_lib = expand_libmacro(libname, path,
16780Sstevel@tonic-gate 				    path)) != NULL)
16790Sstevel@tonic-gate 					libname = _lib;
16800Sstevel@tonic-gate 				else {
16810Sstevel@tonic-gate 					_kobj_printf(ops, "krtld: "
16820Sstevel@tonic-gate 					    "process_dynamic: failed to expand "
16830Sstevel@tonic-gate 					    "%s\n", libname);
16840Sstevel@tonic-gate 				}
16850Sstevel@tonic-gate 			}
16860Sstevel@tonic-gate 
16870Sstevel@tonic-gate 			lsize = strlen(libname);
16880Sstevel@tonic-gate 			nsize += lsize;
16890Sstevel@tonic-gate 			if (nsize + 1 > allocsize) {
16900Sstevel@tonic-gate 				tmp = kobj_alloc(allocsize + MAXPATHLEN,
16910Sstevel@tonic-gate 				    KM_WAIT);
16920Sstevel@tonic-gate 				if (depstr != NULL) {
16930Sstevel@tonic-gate 					bcopy(depstr, tmp, osize);
16940Sstevel@tonic-gate 					kobj_free(depstr, allocsize);
16950Sstevel@tonic-gate 				}
16960Sstevel@tonic-gate 				depstr = tmp;
16970Sstevel@tonic-gate 				allocsize += MAXPATHLEN;
16980Sstevel@tonic-gate 			}
16990Sstevel@tonic-gate 			bcopy(libname, depstr + osize, lsize);
17000Sstevel@tonic-gate 			*(depstr + nsize) = ' '; /* separator */
17010Sstevel@tonic-gate 			nsize++;
17020Sstevel@tonic-gate 			osize = nsize;
17030Sstevel@tonic-gate 			break;
17040Sstevel@tonic-gate 
17050Sstevel@tonic-gate 		case DT_FLAGS_1:
17060Sstevel@tonic-gate 			if (dynp->d_un.d_val & DF_1_IGNMULDEF)
17070Sstevel@tonic-gate 				mp->flags |= KOBJ_IGNMULDEF;
17080Sstevel@tonic-gate 			if (dynp->d_un.d_val & DF_1_NOKSYMS)
17090Sstevel@tonic-gate 				mp->flags |= KOBJ_NOKSYMS;
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 			break;
17120Sstevel@tonic-gate 		}
17130Sstevel@tonic-gate 	}
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	/*
17160Sstevel@tonic-gate 	 * finish up the depends string (if any)
17170Sstevel@tonic-gate 	 */
17180Sstevel@tonic-gate 	if (depstr != NULL) {
17195331Samw 		*(depstr + nsize - 1) = '\0'; /* overwrite separator w/term */
17200Sstevel@tonic-gate 		if (path != NULL)
17210Sstevel@tonic-gate 			kobj_free(path, MAXPATHLEN);
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 		tmp = kobj_alloc(nsize, KM_WAIT);
17240Sstevel@tonic-gate 		bcopy(depstr, tmp, nsize);
17250Sstevel@tonic-gate 		kobj_free(depstr, allocsize);
17260Sstevel@tonic-gate 		depstr = tmp;
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 		mp->depends_on = depstr;
17290Sstevel@tonic-gate 	}
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	return (0);
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate 
17340Sstevel@tonic-gate static int
17350Sstevel@tonic-gate do_dynamic(struct module *mp, struct _buf *file)
17360Sstevel@tonic-gate {
17370Sstevel@tonic-gate 	Shdr *dshp, *dstrp, *shp;
17380Sstevel@tonic-gate 	char *dyndata, *dstrdata;
17390Sstevel@tonic-gate 	int dshn, shn, rc;
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate 	/* find and validate the dynamic section (if any) */
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	for (dshp = NULL, shn = 1; shn < mp->hdr.e_shnum; shn++) {
17440Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
17450Sstevel@tonic-gate 		switch (shp->sh_type) {
17460Sstevel@tonic-gate 		case SHT_DYNAMIC:
17470Sstevel@tonic-gate 			if (dshp != NULL) {
17480Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_dynamic: %s, ",
17490Sstevel@tonic-gate 				    mp->filename);
17500Sstevel@tonic-gate 				_kobj_printf(ops,
17510Sstevel@tonic-gate 				    "multiple dynamic sections\n");
17520Sstevel@tonic-gate 				return (-1);
17530Sstevel@tonic-gate 			} else {
17540Sstevel@tonic-gate 				dshp = shp;
17550Sstevel@tonic-gate 				dshn = shn;
17560Sstevel@tonic-gate 			}
17570Sstevel@tonic-gate 			break;
17580Sstevel@tonic-gate 		}
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	if (dshp == NULL)
17620Sstevel@tonic-gate 		return (0);
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate 	if (dshp->sh_link > mp->hdr.e_shnum) {
17650Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
17660Sstevel@tonic-gate 		_kobj_printf(ops, "no section for sh_link %d\n", dshp->sh_link);
17670Sstevel@tonic-gate 		return (-1);
17680Sstevel@tonic-gate 	}
17690Sstevel@tonic-gate 	dstrp = (Shdr *)(mp->shdrs + dshp->sh_link * mp->hdr.e_shentsize);
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate 	if (dstrp->sh_type != SHT_STRTAB) {
17720Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
17730Sstevel@tonic-gate 		_kobj_printf(ops, "sh_link not a string table for section %d\n",
17740Sstevel@tonic-gate 		    dshn);
17750Sstevel@tonic-gate 		return (-1);
17760Sstevel@tonic-gate 	}
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate 	/* read it from disk */
17790Sstevel@tonic-gate 
17800Sstevel@tonic-gate 	dyndata = kobj_alloc(dshp->sh_size, KM_WAIT|KM_TMP);
17810Sstevel@tonic-gate 	if (kobj_read_file(file, dyndata, dshp->sh_size, dshp->sh_offset) < 0) {
17820Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
17830Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %d\n", dshn);
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate 		kobj_free(dyndata, dshp->sh_size);
17860Sstevel@tonic-gate 		return (-1);
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	dstrdata = kobj_alloc(dstrp->sh_size, KM_WAIT|KM_TMP);
17900Sstevel@tonic-gate 	if (kobj_read_file(file, dstrdata, dstrp->sh_size,
17910Sstevel@tonic-gate 	    dstrp->sh_offset) < 0) {
17920Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
17930Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %d\n", dshp->sh_link);
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate 		kobj_free(dyndata, dshp->sh_size);
17960Sstevel@tonic-gate 		kobj_free(dstrdata, dstrp->sh_size);
17970Sstevel@tonic-gate 		return (-1);
17980Sstevel@tonic-gate 	}
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 	/* pull the interesting pieces out */
18010Sstevel@tonic-gate 
18020Sstevel@tonic-gate 	rc = process_dynamic(mp, dyndata, dstrdata);
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	kobj_free(dyndata, dshp->sh_size);
18050Sstevel@tonic-gate 	kobj_free(dstrdata, dstrp->sh_size);
18060Sstevel@tonic-gate 
18070Sstevel@tonic-gate 	return (rc);
18080Sstevel@tonic-gate }
18090Sstevel@tonic-gate 
18100Sstevel@tonic-gate void
18110Sstevel@tonic-gate kobj_set_ctf(struct module *mp, caddr_t data, size_t size)
18120Sstevel@tonic-gate {
18130Sstevel@tonic-gate 	if (!standalone) {
18140Sstevel@tonic-gate 		if (mp->ctfdata != NULL) {
18150Sstevel@tonic-gate 			if (vmem_contains(ctf_arena, mp->ctfdata,
18163912Slling 			    mp->ctfsize)) {
18170Sstevel@tonic-gate 				vmem_free(ctf_arena, mp->ctfdata, mp->ctfsize);
18180Sstevel@tonic-gate 			} else {
18190Sstevel@tonic-gate 				kobj_free(mp->ctfdata, mp->ctfsize);
18200Sstevel@tonic-gate 			}
18210Sstevel@tonic-gate 		}
18220Sstevel@tonic-gate 	}
18230Sstevel@tonic-gate 
18240Sstevel@tonic-gate 	/*
18250Sstevel@tonic-gate 	 * The order is very important here.  We need to make sure that
18260Sstevel@tonic-gate 	 * consumers, at any given instant, see a consistent state.  We'd
18270Sstevel@tonic-gate 	 * rather they see no CTF data than the address of one buffer and the
18280Sstevel@tonic-gate 	 * size of another.
18290Sstevel@tonic-gate 	 */
18300Sstevel@tonic-gate 	mp->ctfdata = NULL;
18310Sstevel@tonic-gate 	membar_producer();
18320Sstevel@tonic-gate 	mp->ctfsize = size;
18330Sstevel@tonic-gate 	mp->ctfdata = data;
18340Sstevel@tonic-gate 	membar_producer();
18350Sstevel@tonic-gate }
18360Sstevel@tonic-gate 
18370Sstevel@tonic-gate int
18380Sstevel@tonic-gate kobj_load_module(struct modctl *modp, int use_path)
18390Sstevel@tonic-gate {
18400Sstevel@tonic-gate 	char *filename = modp->mod_filename;
18410Sstevel@tonic-gate 	char *modname = modp->mod_modname;
18420Sstevel@tonic-gate 	int i;
18430Sstevel@tonic-gate 	int n;
18440Sstevel@tonic-gate 	struct _buf *file;
18450Sstevel@tonic-gate 	struct module *mp = NULL;
18460Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
18470Sstevel@tonic-gate 	int no_suffixdir_drv = 0;
18480Sstevel@tonic-gate #endif
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 	/*
18530Sstevel@tonic-gate 	 * We need to prevent kmdb's symbols from leaking into /dev/ksyms.
18540Sstevel@tonic-gate 	 * kmdb contains a bunch of symbols with well-known names, symbols
18550Sstevel@tonic-gate 	 * which will mask the real versions, thus causing no end of trouble
18560Sstevel@tonic-gate 	 * for mdb.
18570Sstevel@tonic-gate 	 */
18580Sstevel@tonic-gate 	if (strcmp(modp->mod_modname, "kmdbmod") == 0)
18590Sstevel@tonic-gate 		mp->flags |= KOBJ_NOKSYMS;
18600Sstevel@tonic-gate 
18610Sstevel@tonic-gate 	file = kobj_open_path(filename, use_path, 1);
18620Sstevel@tonic-gate 	if (file == (struct _buf *)-1) {
18630Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
18640Sstevel@tonic-gate 		file = kobj_open_path(filename, use_path, 0);
18650Sstevel@tonic-gate #endif
18660Sstevel@tonic-gate 		if (file == (struct _buf *)-1) {
18670Sstevel@tonic-gate 			kobj_free(mp, sizeof (*mp));
18680Sstevel@tonic-gate 			goto bad;
18690Sstevel@tonic-gate 		}
18700Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
18710Sstevel@tonic-gate 		/*
18720Sstevel@tonic-gate 		 * There is no driver module in the ISA specific (suffix)
18730Sstevel@tonic-gate 		 * subdirectory but there is a module in the parent directory.
18740Sstevel@tonic-gate 		 */
18750Sstevel@tonic-gate 		if (strncmp(filename, "drv/", 4) == 0) {
18760Sstevel@tonic-gate 			no_suffixdir_drv = 1;
18770Sstevel@tonic-gate 		}
18780Sstevel@tonic-gate #endif
18790Sstevel@tonic-gate 	}
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate 	mp->filename = kobj_alloc(strlen(file->_name) + 1, KM_WAIT);
18820Sstevel@tonic-gate 	(void) strcpy(mp->filename, file->_name);
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 	if (kobj_read_file(file, (char *)&mp->hdr, sizeof (mp->hdr), 0) < 0) {
18850Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_load_module: %s read header failed\n",
18860Sstevel@tonic-gate 		    modname);
18870Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
18880Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
18890Sstevel@tonic-gate 		goto bad;
18900Sstevel@tonic-gate 	}
18910Sstevel@tonic-gate 	for (i = 0; i < SELFMAG; i++) {
18920Sstevel@tonic-gate 		if (mp->hdr.e_ident[i] != ELFMAG[i]) {
18930Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG)
18940Sstevel@tonic-gate 				_kobj_printf(ops, "%s not an elf module\n",
18950Sstevel@tonic-gate 				    modname);
18960Sstevel@tonic-gate 			kobj_free(mp->filename, strlen(file->_name) + 1);
18970Sstevel@tonic-gate 			kobj_free(mp, sizeof (*mp));
18980Sstevel@tonic-gate 			goto bad;
18990Sstevel@tonic-gate 		}
19000Sstevel@tonic-gate 	}
19010Sstevel@tonic-gate 	/*
19020Sstevel@tonic-gate 	 * It's ELF, but is it our ISA?  Interpreting the header
19030Sstevel@tonic-gate 	 * from a file for a byte-swapped ISA could cause a huge
19040Sstevel@tonic-gate 	 * and unsatisfiable value to be passed to kobj_alloc below
19050Sstevel@tonic-gate 	 * and therefore hang booting.
19060Sstevel@tonic-gate 	 */
19070Sstevel@tonic-gate 	if (!elf_mach_ok(&mp->hdr)) {
19080Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG)
19090Sstevel@tonic-gate 			_kobj_printf(ops, "%s not an elf module for this ISA\n",
19100Sstevel@tonic-gate 			    modname);
19110Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
19120Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
19130Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
19140Sstevel@tonic-gate 		/*
19150Sstevel@tonic-gate 		 * The driver mod is not in the ISA specific subdirectory
19160Sstevel@tonic-gate 		 * and the module in the parent directory is not our ISA.
19170Sstevel@tonic-gate 		 * If it is our ISA, for now we will silently succeed.
19180Sstevel@tonic-gate 		 */
19190Sstevel@tonic-gate 		if (no_suffixdir_drv == 1) {
19200Sstevel@tonic-gate 			cmn_err(CE_CONT, "?NOTICE: %s: 64-bit driver module"
19210Sstevel@tonic-gate 			    " not found\n", modname);
19220Sstevel@tonic-gate 		}
19230Sstevel@tonic-gate #endif
19240Sstevel@tonic-gate 		goto bad;
19250Sstevel@tonic-gate 	}
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 	/*
19280Sstevel@tonic-gate 	 * All modules, save for unix, should be relocatable (as opposed to
19290Sstevel@tonic-gate 	 * dynamic).  Dynamic modules come with PLTs and GOTs, which can't
19300Sstevel@tonic-gate 	 * currently be processed by krtld.
19310Sstevel@tonic-gate 	 */
19320Sstevel@tonic-gate 	if (mp->hdr.e_type != ET_REL) {
19330Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG)
19340Sstevel@tonic-gate 			_kobj_printf(ops, "%s isn't a relocatable (ET_REL) "
19350Sstevel@tonic-gate 			    "module\n", modname);
19360Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
19370Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
19380Sstevel@tonic-gate 		goto bad;
19390Sstevel@tonic-gate 	}
19400Sstevel@tonic-gate 
19410Sstevel@tonic-gate 	n = mp->hdr.e_shentsize * mp->hdr.e_shnum;
19420Sstevel@tonic-gate 	mp->shdrs = kobj_alloc(n, KM_WAIT);
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 	if (kobj_read_file(file, mp->shdrs, n, mp->hdr.e_shoff) < 0) {
19450Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_load_module: %s error reading "
19460Sstevel@tonic-gate 		    "section headers\n", modname);
19470Sstevel@tonic-gate 		kobj_free(mp->shdrs, n);
19480Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
19490Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
19500Sstevel@tonic-gate 		goto bad;
19510Sstevel@tonic-gate 	}
19520Sstevel@tonic-gate 
19530Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODLOADING, modp);
19540Sstevel@tonic-gate 	module_assign(modp, mp);
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 	/* read in sections */
19570Sstevel@tonic-gate 	if (get_progbits(mp, file) < 0) {
19580Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading sections\n", modname);
19590Sstevel@tonic-gate 		goto bad;
19600Sstevel@tonic-gate 	}
19610Sstevel@tonic-gate 
19620Sstevel@tonic-gate 	if (do_dynamic(mp, file) < 0) {
19630Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading dynamic section\n",
19640Sstevel@tonic-gate 		    modname);
19650Sstevel@tonic-gate 		goto bad;
19660Sstevel@tonic-gate 	}
19670Sstevel@tonic-gate 
19680Sstevel@tonic-gate 	modp->mod_text = mp->text;
19690Sstevel@tonic-gate 	modp->mod_text_size = mp->text_size;
19700Sstevel@tonic-gate 
19710Sstevel@tonic-gate 	/* read in symbols; adjust values for each section's real address */
19720Sstevel@tonic-gate 	if (get_syms(mp, file) < 0) {
19730Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading symbols\n",
19740Sstevel@tonic-gate 		    modname);
19750Sstevel@tonic-gate 		goto bad;
19760Sstevel@tonic-gate 	}
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 	/*
19790Sstevel@tonic-gate 	 * If we didn't dependency information from the dynamic section, look
19800Sstevel@tonic-gate 	 * for it the old-fashioned way.
19810Sstevel@tonic-gate 	 */
19820Sstevel@tonic-gate 	if (mp->depends_on == NULL)
19830Sstevel@tonic-gate 		mp->depends_on = depends_on(mp);
19840Sstevel@tonic-gate 
19850Sstevel@tonic-gate 	if (get_ctf(mp, file) < 0) {
19860Sstevel@tonic-gate 		_kobj_printf(ops, "%s debug information will not "
19870Sstevel@tonic-gate 		    "be available\n", modname);
19880Sstevel@tonic-gate 	}
19890Sstevel@tonic-gate 
19900Sstevel@tonic-gate 	/* primary kernel modules do not have a signature section */
19910Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_PRIM))
19920Sstevel@tonic-gate 		get_signature(mp, file);
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
19950Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
19960Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
19970Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext:0x%p", mp->text);
19980Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
19990Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata:0x%p", mp->data);
20000Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
20010Sstevel@tonic-gate 	}
20020Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
20030Sstevel@tonic-gate 
20040Sstevel@tonic-gate 	/*
20050Sstevel@tonic-gate 	 * For primary kernel modules, we defer
20060Sstevel@tonic-gate 	 * symbol resolution and relocation until
20070Sstevel@tonic-gate 	 * all primary objects have been loaded.
20080Sstevel@tonic-gate 	 */
20090Sstevel@tonic-gate 	if (!standalone) {
20100Sstevel@tonic-gate 		int ddrval, dcrval;
20110Sstevel@tonic-gate 		char *dependent_modname;
20120Sstevel@tonic-gate 		/* load all dependents */
20130Sstevel@tonic-gate 		dependent_modname = kobj_zalloc(MODMAXNAMELEN, KM_WAIT);
20140Sstevel@tonic-gate 		ddrval = do_dependents(modp, dependent_modname, MODMAXNAMELEN);
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 		/*
20170Sstevel@tonic-gate 		 * resolve undefined and common symbols,
20180Sstevel@tonic-gate 		 * also allocates common space
20190Sstevel@tonic-gate 		 */
20200Sstevel@tonic-gate 		if ((dcrval = do_common(mp)) < 0) {
20210Sstevel@tonic-gate 			switch (dcrval) {
20220Sstevel@tonic-gate 			case DOSYM_UNSAFE:
20230Sstevel@tonic-gate 				_kobj_printf(ops, "WARNING: mod_load: "
20240Sstevel@tonic-gate 				    "MT-unsafe module '%s' rejected\n",
20250Sstevel@tonic-gate 				    modname);
20260Sstevel@tonic-gate 				break;
20270Sstevel@tonic-gate 			case DOSYM_UNDEF:
20280Sstevel@tonic-gate 				_kobj_printf(ops, "WARNING: mod_load: "
20290Sstevel@tonic-gate 				    "cannot load module '%s'\n",
20300Sstevel@tonic-gate 				    modname);
20310Sstevel@tonic-gate 				if (ddrval == -1) {
20320Sstevel@tonic-gate 					_kobj_printf(ops, "WARNING: %s: ",
20330Sstevel@tonic-gate 					    modname);
20340Sstevel@tonic-gate 					_kobj_printf(ops,
20350Sstevel@tonic-gate 					    "unable to resolve dependency, "
20360Sstevel@tonic-gate 					    "module '%s' not found\n",
20370Sstevel@tonic-gate 					    dependent_modname);
20380Sstevel@tonic-gate 				}
20390Sstevel@tonic-gate 				break;
20400Sstevel@tonic-gate 			}
20410Sstevel@tonic-gate 		}
20420Sstevel@tonic-gate 		kobj_free(dependent_modname, MODMAXNAMELEN);
20430Sstevel@tonic-gate 		if (dcrval < 0)
20440Sstevel@tonic-gate 			goto bad;
20450Sstevel@tonic-gate 
20460Sstevel@tonic-gate 		/* process relocation tables */
20470Sstevel@tonic-gate 		if (do_relocations(mp) < 0) {
20480Sstevel@tonic-gate 			_kobj_printf(ops, "%s error doing relocations\n",
20490Sstevel@tonic-gate 			    modname);
20500Sstevel@tonic-gate 			goto bad;
20510Sstevel@tonic-gate 		}
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 		if (mp->destination) {
20540Sstevel@tonic-gate 			off_t	off = (uintptr_t)mp->destination & PAGEOFFSET;
20550Sstevel@tonic-gate 			caddr_t	base = (caddr_t)mp->destination - off;
20560Sstevel@tonic-gate 			size_t	size = P2ROUNDUP(mp->text_size + off, PAGESIZE);
20570Sstevel@tonic-gate 
20580Sstevel@tonic-gate 			hat_unload(kas.a_hat, base, size, HAT_UNLOAD_UNLOCK);
20590Sstevel@tonic-gate 			vmem_free(heap_arena, base, size);
20600Sstevel@tonic-gate 		}
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate 		/* sync_instruction_memory */
20630Sstevel@tonic-gate 		kobj_sync_instruction_memory(mp->text, mp->text_size);
20640Sstevel@tonic-gate 		kobj_export_module(mp);
20650Sstevel@tonic-gate 		kobj_notify(KOBJ_NOTIFY_MODLOADED, modp);
20660Sstevel@tonic-gate 	}
20670Sstevel@tonic-gate 	kobj_close_file(file);
20680Sstevel@tonic-gate 	return (0);
20690Sstevel@tonic-gate bad:
20700Sstevel@tonic-gate 	if (file != (struct _buf *)-1)
20710Sstevel@tonic-gate 		kobj_close_file(file);
20720Sstevel@tonic-gate 	if (modp->mod_mp != NULL)
20730Sstevel@tonic-gate 		free_module_data(modp->mod_mp);
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate 	module_assign(modp, NULL);
20760Sstevel@tonic-gate 	return ((file == (struct _buf *)-1) ? ENOENT : EINVAL);
20770Sstevel@tonic-gate }
20780Sstevel@tonic-gate 
20790Sstevel@tonic-gate int
20800Sstevel@tonic-gate kobj_load_primary_module(struct modctl *modp)
20810Sstevel@tonic-gate {
20820Sstevel@tonic-gate 	struct modctl *dep;
20830Sstevel@tonic-gate 	struct module *mp;
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 	if (kobj_load_module(modp, 0) != 0)
20860Sstevel@tonic-gate 		return (-1);
20870Sstevel@tonic-gate 
20880Sstevel@tonic-gate 	mp = modp->mod_mp;
20890Sstevel@tonic-gate 	mp->flags |= KOBJ_PRIM;
20900Sstevel@tonic-gate 
20910Sstevel@tonic-gate 	/* Bind new module to its dependents */
20920Sstevel@tonic-gate 	if (mp->depends_on != NULL && (dep =
20930Sstevel@tonic-gate 	    mod_already_loaded(mp->depends_on)) == NULL) {
20940Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
20950Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG) {
20960Sstevel@tonic-gate 			_kobj_printf(ops, "krtld: failed to resolve deps "
20970Sstevel@tonic-gate 			    "for primary %s\n", modp->mod_modname);
20980Sstevel@tonic-gate 		}
20990Sstevel@tonic-gate #endif
21000Sstevel@tonic-gate 		return (-1);
21010Sstevel@tonic-gate 	}
21020Sstevel@tonic-gate 
21030Sstevel@tonic-gate 	add_dependent(mp, dep->mod_mp);
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	/*
21060Sstevel@tonic-gate 	 * Relocate it.  This module may not be part of a link map, so we
21070Sstevel@tonic-gate 	 * can't use bind_primary.
21080Sstevel@tonic-gate 	 */
21090Sstevel@tonic-gate 	if (do_common(mp) < 0 || do_symbols(mp, 0) < 0 ||
21100Sstevel@tonic-gate 	    do_relocations(mp) < 0) {
21110Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
21120Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG) {
21130Sstevel@tonic-gate 			_kobj_printf(ops, "krtld: failed to relocate "
21140Sstevel@tonic-gate 			    "primary %s\n", modp->mod_modname);
21150Sstevel@tonic-gate 		}
21160Sstevel@tonic-gate #endif
21170Sstevel@tonic-gate 		return (-1);
21180Sstevel@tonic-gate 	}
21190Sstevel@tonic-gate 
21200Sstevel@tonic-gate 	return (0);
21210Sstevel@tonic-gate }
21220Sstevel@tonic-gate 
21230Sstevel@tonic-gate static void
21240Sstevel@tonic-gate module_assign(struct modctl *cp, struct module *mp)
21250Sstevel@tonic-gate {
21260Sstevel@tonic-gate 	if (standalone) {
21270Sstevel@tonic-gate 		cp->mod_mp = mp;
21280Sstevel@tonic-gate 		return;
21290Sstevel@tonic-gate 	}
21300Sstevel@tonic-gate 	mutex_enter(&mod_lock);
21310Sstevel@tonic-gate 	cp->mod_mp = mp;
21320Sstevel@tonic-gate 	cp->mod_gencount++;
21330Sstevel@tonic-gate 	mutex_exit(&mod_lock);
21340Sstevel@tonic-gate }
21350Sstevel@tonic-gate 
21360Sstevel@tonic-gate void
21370Sstevel@tonic-gate kobj_unload_module(struct modctl *modp)
21380Sstevel@tonic-gate {
21390Sstevel@tonic-gate 	struct module *mp = modp->mod_mp;
21400Sstevel@tonic-gate 
21410Sstevel@tonic-gate 	if ((_moddebug & MODDEBUG_KEEPTEXT) && mp) {
21420Sstevel@tonic-gate 		_kobj_printf(ops, "text for %s ", mp->filename);
21430Sstevel@tonic-gate 		_kobj_printf(ops, "was at %p\n", mp->text);
21440Sstevel@tonic-gate 		mp->text = NULL;	/* don't actually free it */
21450Sstevel@tonic-gate 	}
21460Sstevel@tonic-gate 
21470Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODUNLOADING, modp);
21480Sstevel@tonic-gate 
21490Sstevel@tonic-gate 	/*
21500Sstevel@tonic-gate 	 * Null out mod_mp first, so consumers (debuggers) know not to look
21510Sstevel@tonic-gate 	 * at the module structure any more.
21520Sstevel@tonic-gate 	 */
21530Sstevel@tonic-gate 	mutex_enter(&mod_lock);
21540Sstevel@tonic-gate 	modp->mod_mp = NULL;
21550Sstevel@tonic-gate 	mutex_exit(&mod_lock);
21560Sstevel@tonic-gate 
21570Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODUNLOADED, modp);
21580Sstevel@tonic-gate 	free_module_data(mp);
21590Sstevel@tonic-gate }
21600Sstevel@tonic-gate 
21610Sstevel@tonic-gate static void
21620Sstevel@tonic-gate free_module_data(struct module *mp)
21630Sstevel@tonic-gate {
21640Sstevel@tonic-gate 	struct module_list *lp, *tmp;
21650Sstevel@tonic-gate 	int ksyms_exported = 0;
21660Sstevel@tonic-gate 
21670Sstevel@tonic-gate 	lp = mp->head;
21680Sstevel@tonic-gate 	while (lp) {
21690Sstevel@tonic-gate 		tmp = lp;
21700Sstevel@tonic-gate 		lp = lp->next;
21710Sstevel@tonic-gate 		kobj_free((char *)tmp, sizeof (*tmp));
21720Sstevel@tonic-gate 	}
21730Sstevel@tonic-gate 
21740Sstevel@tonic-gate 	rw_enter(&ksyms_lock, RW_WRITER);
21750Sstevel@tonic-gate 	if (mp->symspace) {
21760Sstevel@tonic-gate 		if (vmem_contains(ksyms_arena, mp->symspace, mp->symsize)) {
21770Sstevel@tonic-gate 			vmem_free(ksyms_arena, mp->symspace, mp->symsize);
21780Sstevel@tonic-gate 			ksyms_exported = 1;
21790Sstevel@tonic-gate 		} else {
21800Sstevel@tonic-gate 			if (mp->flags & KOBJ_NOKSYMS)
21810Sstevel@tonic-gate 				ksyms_exported = 1;
21820Sstevel@tonic-gate 			kobj_free(mp->symspace, mp->symsize);
21830Sstevel@tonic-gate 		}
21840Sstevel@tonic-gate 	}
21850Sstevel@tonic-gate 	rw_exit(&ksyms_lock);
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 	if (mp->ctfdata) {
21880Sstevel@tonic-gate 		if (vmem_contains(ctf_arena, mp->ctfdata, mp->ctfsize))
21890Sstevel@tonic-gate 			vmem_free(ctf_arena, mp->ctfdata, mp->ctfsize);
21900Sstevel@tonic-gate 		else
21910Sstevel@tonic-gate 			kobj_free(mp->ctfdata, mp->ctfsize);
21920Sstevel@tonic-gate 	}
21930Sstevel@tonic-gate 
21940Sstevel@tonic-gate 	if (mp->sigdata)
21950Sstevel@tonic-gate 		kobj_free(mp->sigdata, mp->sigsize);
21960Sstevel@tonic-gate 
21970Sstevel@tonic-gate 	/*
21980Sstevel@tonic-gate 	 * We did not get far enough into kobj_export_ksyms() to free allocated
21990Sstevel@tonic-gate 	 * buffers because we encounted error conditions. Free the buffers.
22000Sstevel@tonic-gate 	 */
22010Sstevel@tonic-gate 	if ((ksyms_exported == 0) && (mp->shdrs != NULL)) {
22020Sstevel@tonic-gate 		uint_t shn;
22030Sstevel@tonic-gate 		Shdr *shp;
22040Sstevel@tonic-gate 
22050Sstevel@tonic-gate 		for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
22060Sstevel@tonic-gate 			shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
22070Sstevel@tonic-gate 			switch (shp->sh_type) {
22080Sstevel@tonic-gate 			case SHT_RELA:
22090Sstevel@tonic-gate 			case SHT_REL:
22100Sstevel@tonic-gate 				if (shp->sh_addr != 0)
22110Sstevel@tonic-gate 					kobj_free((void *)shp->sh_addr,
22120Sstevel@tonic-gate 					    shp->sh_size);
22130Sstevel@tonic-gate 				break;
22140Sstevel@tonic-gate 			}
22150Sstevel@tonic-gate 		}
22160Sstevel@tonic-gate err_free_done:
22170Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_PRIM)) {
22180Sstevel@tonic-gate 			kobj_free(mp->shdrs,
22190Sstevel@tonic-gate 			    mp->hdr.e_shentsize * mp->hdr.e_shnum);
22200Sstevel@tonic-gate 		}
22210Sstevel@tonic-gate 	}
22220Sstevel@tonic-gate 
22230Sstevel@tonic-gate 	if (mp->bss)
22240Sstevel@tonic-gate 		vmem_free(data_arena, (void *)mp->bss, mp->bss_size);
22250Sstevel@tonic-gate 
22260Sstevel@tonic-gate 	if (mp->fbt_tab)
22270Sstevel@tonic-gate 		kobj_texthole_free(mp->fbt_tab, mp->fbt_size);
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate 	if (mp->textwin_base)
22300Sstevel@tonic-gate 		kobj_textwin_free(mp);
22310Sstevel@tonic-gate 
22320Sstevel@tonic-gate 	if (mp->sdt_probes != NULL) {
22330Sstevel@tonic-gate 		sdt_probedesc_t *sdp = mp->sdt_probes, *next;
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate 		while (sdp != NULL) {
22360Sstevel@tonic-gate 			next = sdp->sdpd_next;
22370Sstevel@tonic-gate 			kobj_free(sdp->sdpd_name, strlen(sdp->sdpd_name) + 1);
22380Sstevel@tonic-gate 			kobj_free(sdp, sizeof (sdt_probedesc_t));
22390Sstevel@tonic-gate 			sdp = next;
22400Sstevel@tonic-gate 		}
22410Sstevel@tonic-gate 	}
22420Sstevel@tonic-gate 
22430Sstevel@tonic-gate 	if (mp->sdt_tab)
22440Sstevel@tonic-gate 		kobj_texthole_free(mp->sdt_tab, mp->sdt_size);
22450Sstevel@tonic-gate 	if (mp->text)
22460Sstevel@tonic-gate 		vmem_free(text_arena, mp->text, mp->text_size);
22470Sstevel@tonic-gate 	if (mp->data)
22480Sstevel@tonic-gate 		vmem_free(data_arena, mp->data, mp->data_size);
22490Sstevel@tonic-gate 	if (mp->depends_on)
22500Sstevel@tonic-gate 		kobj_free(mp->depends_on, strlen(mp->depends_on)+1);
22510Sstevel@tonic-gate 	if (mp->filename)
22520Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(mp->filename)+1);
22530Sstevel@tonic-gate 
22540Sstevel@tonic-gate 	kobj_free((char *)mp, sizeof (*mp));
22550Sstevel@tonic-gate }
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate static int
22580Sstevel@tonic-gate get_progbits(struct module *mp, struct _buf *file)
22590Sstevel@tonic-gate {
22600Sstevel@tonic-gate 	struct proginfo *tp, *dp, *sdp;
22610Sstevel@tonic-gate 	Shdr *shp;
22620Sstevel@tonic-gate 	reloc_dest_t dest = NULL;
22630Sstevel@tonic-gate 	uintptr_t bits_ptr;
22646206Sab196087 	uintptr_t text = 0, data, textptr;
22650Sstevel@tonic-gate 	uint_t shn;
22660Sstevel@tonic-gate 	int err = -1;
22670Sstevel@tonic-gate 
22685648Ssetje 	tp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP);
22695648Ssetje 	dp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP);
22705648Ssetje 	sdp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT|KM_TMP);
22710Sstevel@tonic-gate 	/*
22720Sstevel@tonic-gate 	 * loop through sections to find out how much space we need
22730Sstevel@tonic-gate 	 * for text, data, (also bss that is already assigned)
22740Sstevel@tonic-gate 	 */
22750Sstevel@tonic-gate 	if (get_progbits_size(mp, tp, dp, sdp) < 0)
22760Sstevel@tonic-gate 		goto done;
22770Sstevel@tonic-gate 
22780Sstevel@tonic-gate 	mp->text_size = tp->size;
22790Sstevel@tonic-gate 	mp->data_size = dp->size;
22800Sstevel@tonic-gate 
22810Sstevel@tonic-gate 	if (standalone) {
22823446Smrj 		caddr_t limit = _data;
22833446Smrj 
22843446Smrj 		if (lg_pagesize && _text + lg_pagesize < limit)
22853446Smrj 			limit = _text + lg_pagesize;
22863446Smrj 
22870Sstevel@tonic-gate 		mp->text = kobj_segbrk(&_etext, mp->text_size,
22883912Slling 		    tp->align, limit);
22890Sstevel@tonic-gate 		/*
22900Sstevel@tonic-gate 		 * If we can't grow the text segment, try the
22910Sstevel@tonic-gate 		 * data segment before failing.
22920Sstevel@tonic-gate 		 */
22930Sstevel@tonic-gate 		if (mp->text == NULL) {
22940Sstevel@tonic-gate 			mp->text = kobj_segbrk(&_edata, mp->text_size,
22953912Slling 			    tp->align, 0);
22960Sstevel@tonic-gate 		}
22970Sstevel@tonic-gate 
22980Sstevel@tonic-gate 		mp->data = kobj_segbrk(&_edata, mp->data_size, dp->align, 0);
22990Sstevel@tonic-gate 
23000Sstevel@tonic-gate 		if (mp->text == NULL || mp->data == NULL)
23010Sstevel@tonic-gate 			goto done;
23020Sstevel@tonic-gate 
23030Sstevel@tonic-gate 	} else {
23040Sstevel@tonic-gate 		if (text_arena == NULL)
23050Sstevel@tonic-gate 			kobj_vmem_init(&text_arena, &data_arena);
23060Sstevel@tonic-gate 
23070Sstevel@tonic-gate 		/*
23080Sstevel@tonic-gate 		 * some architectures may want to load the module on a
23090Sstevel@tonic-gate 		 * page that is currently read only. It may not be
23100Sstevel@tonic-gate 		 * possible for those architectures to remap their page
23110Sstevel@tonic-gate 		 * on the fly. So we provide a facility for them to hang
23120Sstevel@tonic-gate 		 * a private hook where the memory they assign the module
23130Sstevel@tonic-gate 		 * is not the actual place where the module loads.
23140Sstevel@tonic-gate 		 *
23150Sstevel@tonic-gate 		 * In this case there are two addresses that deal with the
23160Sstevel@tonic-gate 		 * modload.
23170Sstevel@tonic-gate 		 * 1) the final destination of the module
23180Sstevel@tonic-gate 		 * 2) the address that is used to view the newly
23190Sstevel@tonic-gate 		 * loaded module until all the relocations relative to 1
23200Sstevel@tonic-gate 		 * above are completed.
23210Sstevel@tonic-gate 		 *
23220Sstevel@tonic-gate 		 * That is what dest is used for below.
23230Sstevel@tonic-gate 		 */
23240Sstevel@tonic-gate 		mp->text_size += tp->align;
23250Sstevel@tonic-gate 		mp->data_size += dp->align;
23260Sstevel@tonic-gate 
23270Sstevel@tonic-gate 		mp->text = kobj_text_alloc(text_arena, mp->text_size);
23280Sstevel@tonic-gate 
23290Sstevel@tonic-gate 		/*
23300Sstevel@tonic-gate 		 * a remap is taking place. Align the text ptr relative
23310Sstevel@tonic-gate 		 * to the secondary mapping. That is where the bits will
23320Sstevel@tonic-gate 		 * be read in.
23330Sstevel@tonic-gate 		 */
23340Sstevel@tonic-gate 		if (kvseg.s_base != NULL && !vmem_contains(heaptext_arena,
23350Sstevel@tonic-gate 		    mp->text, mp->text_size)) {
23360Sstevel@tonic-gate 			off_t	off = (uintptr_t)mp->text & PAGEOFFSET;
23370Sstevel@tonic-gate 			size_t	size = P2ROUNDUP(mp->text_size + off, PAGESIZE);
23380Sstevel@tonic-gate 			caddr_t	map = vmem_alloc(heap_arena, size, VM_SLEEP);
23390Sstevel@tonic-gate 			caddr_t orig = mp->text - off;
23400Sstevel@tonic-gate 			pgcnt_t pages = size / PAGESIZE;
23410Sstevel@tonic-gate 
23420Sstevel@tonic-gate 			dest = (reloc_dest_t)(map + off);
23430Sstevel@tonic-gate 			text = ALIGN((uintptr_t)dest, tp->align);
23440Sstevel@tonic-gate 
23450Sstevel@tonic-gate 			while (pages--) {
23460Sstevel@tonic-gate 				hat_devload(kas.a_hat, map, PAGESIZE,
23470Sstevel@tonic-gate 				    hat_getpfnum(kas.a_hat, orig),
23480Sstevel@tonic-gate 				    PROT_READ | PROT_WRITE | PROT_EXEC,
23490Sstevel@tonic-gate 				    HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
23500Sstevel@tonic-gate 				map += PAGESIZE;
23510Sstevel@tonic-gate 				orig += PAGESIZE;
23520Sstevel@tonic-gate 			}
23530Sstevel@tonic-gate 			/*
23540Sstevel@tonic-gate 			 * Since we set up a non-cacheable mapping, we need
23550Sstevel@tonic-gate 			 * to flush any old entries in the cache that might
23560Sstevel@tonic-gate 			 * be left around from the read-only mapping.
23570Sstevel@tonic-gate 			 */
23580Sstevel@tonic-gate 			dcache_flushall();
23590Sstevel@tonic-gate 		}
23600Sstevel@tonic-gate 		if (mp->data_size)
23610Sstevel@tonic-gate 			mp->data = vmem_alloc(data_arena, mp->data_size,
23620Sstevel@tonic-gate 			    VM_SLEEP | VM_BESTFIT);
23630Sstevel@tonic-gate 	}
23640Sstevel@tonic-gate 	textptr = (uintptr_t)mp->text;
23650Sstevel@tonic-gate 	textptr = ALIGN(textptr, tp->align);
23660Sstevel@tonic-gate 	mp->destination = dest;
23670Sstevel@tonic-gate 
23680Sstevel@tonic-gate 	/*
23690Sstevel@tonic-gate 	 * This is the case where a remap is not being done.
23700Sstevel@tonic-gate 	 */
23710Sstevel@tonic-gate 	if (text == 0)
23720Sstevel@tonic-gate 		text = ALIGN((uintptr_t)mp->text, tp->align);
23730Sstevel@tonic-gate 	data = ALIGN((uintptr_t)mp->data, dp->align);
23740Sstevel@tonic-gate 
23750Sstevel@tonic-gate 	/* now loop though sections assigning addresses and loading the data */
23760Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
23770Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
23780Sstevel@tonic-gate 		if (!(shp->sh_flags & SHF_ALLOC))
23790Sstevel@tonic-gate 			continue;
23800Sstevel@tonic-gate 
23810Sstevel@tonic-gate 		if ((shp->sh_flags & SHF_WRITE) == 0)
23820Sstevel@tonic-gate 			bits_ptr = text;
23830Sstevel@tonic-gate 		else
23840Sstevel@tonic-gate 			bits_ptr = data;
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate 		bits_ptr = ALIGN(bits_ptr, shp->sh_addralign);
23870Sstevel@tonic-gate 
23880Sstevel@tonic-gate 		if (shp->sh_type == SHT_NOBITS) {
23890Sstevel@tonic-gate 			/*
23900Sstevel@tonic-gate 			 * Zero bss.
23910Sstevel@tonic-gate 			 */
23920Sstevel@tonic-gate 			bzero((caddr_t)bits_ptr, shp->sh_size);
23930Sstevel@tonic-gate 			shp->sh_type = SHT_PROGBITS;
23940Sstevel@tonic-gate 		} else {
23950Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)bits_ptr,
23960Sstevel@tonic-gate 			    shp->sh_size, shp->sh_offset) < 0)
23970Sstevel@tonic-gate 				goto done;
23980Sstevel@tonic-gate 		}
23990Sstevel@tonic-gate 
24000Sstevel@tonic-gate 		if (shp->sh_flags & SHF_WRITE) {
24010Sstevel@tonic-gate 			shp->sh_addr = bits_ptr;
24020Sstevel@tonic-gate 		} else {
24030Sstevel@tonic-gate 			textptr = ALIGN(textptr, shp->sh_addralign);
24040Sstevel@tonic-gate 			shp->sh_addr = textptr;
24050Sstevel@tonic-gate 			textptr += shp->sh_size;
24060Sstevel@tonic-gate 		}
24070Sstevel@tonic-gate 
24080Sstevel@tonic-gate 		bits_ptr += shp->sh_size;
24090Sstevel@tonic-gate 		if ((shp->sh_flags & SHF_WRITE) == 0)
24100Sstevel@tonic-gate 			text = bits_ptr;
24110Sstevel@tonic-gate 		else
24120Sstevel@tonic-gate 			data = bits_ptr;
24130Sstevel@tonic-gate 	}
24140Sstevel@tonic-gate 
24150Sstevel@tonic-gate 	err = 0;
24160Sstevel@tonic-gate done:
24170Sstevel@tonic-gate 	/*
24180Sstevel@tonic-gate 	 * Free and mark as freed the section headers here so that
24190Sstevel@tonic-gate 	 * free_module_data() does not have to worry about this buffer.
24200Sstevel@tonic-gate 	 *
24210Sstevel@tonic-gate 	 * This buffer is freed here because one of the possible reasons
24220Sstevel@tonic-gate 	 * for error is a section with non-zero sh_addr and in that case
24230Sstevel@tonic-gate 	 * free_module_data() would have no way of recognizing that this
24240Sstevel@tonic-gate 	 * buffer was unallocated.
24250Sstevel@tonic-gate 	 */
24260Sstevel@tonic-gate 	if (err != 0) {
24270Sstevel@tonic-gate 		kobj_free(mp->shdrs, mp->hdr.e_shentsize * mp->hdr.e_shnum);
24280Sstevel@tonic-gate 		mp->shdrs = NULL;
24290Sstevel@tonic-gate 	}
24300Sstevel@tonic-gate 
24310Sstevel@tonic-gate 	(void) kobj_free(tp, sizeof (struct proginfo));
24320Sstevel@tonic-gate 	(void) kobj_free(dp, sizeof (struct proginfo));
24330Sstevel@tonic-gate 	(void) kobj_free(sdp, sizeof (struct proginfo));
24340Sstevel@tonic-gate 
24350Sstevel@tonic-gate 	return (err);
24360Sstevel@tonic-gate }
24370Sstevel@tonic-gate 
24380Sstevel@tonic-gate /*
24390Sstevel@tonic-gate  * Go through suppress_sym_list to see if "multiply defined"
24400Sstevel@tonic-gate  * warning of this symbol should be suppressed.  Return 1 if
24410Sstevel@tonic-gate  * warning should be suppressed, 0 otherwise.
24420Sstevel@tonic-gate  */
24430Sstevel@tonic-gate static int
24440Sstevel@tonic-gate kobj_suppress_warning(char *symname)
24450Sstevel@tonic-gate {
24460Sstevel@tonic-gate 	int	i;
24470Sstevel@tonic-gate 
24480Sstevel@tonic-gate 	for (i = 0; suppress_sym_list[i] != NULL; i++) {
24490Sstevel@tonic-gate 		if (strcmp(suppress_sym_list[i], symname) == 0)
24500Sstevel@tonic-gate 			return (1);
24510Sstevel@tonic-gate 	}
24520Sstevel@tonic-gate 
24530Sstevel@tonic-gate 	return (0);
24540Sstevel@tonic-gate }
24550Sstevel@tonic-gate 
24560Sstevel@tonic-gate static int
24570Sstevel@tonic-gate get_syms(struct module *mp, struct _buf *file)
24580Sstevel@tonic-gate {
24590Sstevel@tonic-gate 	uint_t		shn;
24600Sstevel@tonic-gate 	Shdr	*shp;
24610Sstevel@tonic-gate 	uint_t		i;
24620Sstevel@tonic-gate 	Sym	*sp, *ksp;
24630Sstevel@tonic-gate 	char		*symname;
24640Sstevel@tonic-gate 	int		dosymtab = 0;
24650Sstevel@tonic-gate 
24660Sstevel@tonic-gate 	/*
24670Sstevel@tonic-gate 	 * Find the interesting sections.
24680Sstevel@tonic-gate 	 */
24690Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
24700Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
24710Sstevel@tonic-gate 		switch (shp->sh_type) {
24720Sstevel@tonic-gate 		case SHT_SYMTAB:
24730Sstevel@tonic-gate 			mp->symtbl_section = shn;
24740Sstevel@tonic-gate 			mp->symhdr = shp;
24750Sstevel@tonic-gate 			dosymtab++;
24760Sstevel@tonic-gate 			break;
24770Sstevel@tonic-gate 
24780Sstevel@tonic-gate 		case SHT_RELA:
24790Sstevel@tonic-gate 		case SHT_REL:
24800Sstevel@tonic-gate 			/*
24810Sstevel@tonic-gate 			 * Already loaded.
24820Sstevel@tonic-gate 			 */
24830Sstevel@tonic-gate 			if (shp->sh_addr)
24840Sstevel@tonic-gate 				continue;
24855648Ssetje 
24865648Ssetje 			/* KM_TMP since kobj_free'd in do_relocations */
24870Sstevel@tonic-gate 			shp->sh_addr = (Addr)
24880Sstevel@tonic-gate 			    kobj_alloc(shp->sh_size, KM_WAIT|KM_TMP);
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)shp->sh_addr,
24910Sstevel@tonic-gate 			    shp->sh_size, shp->sh_offset) < 0) {
24920Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_syms: %s, ",
24930Sstevel@tonic-gate 				    mp->filename);
24940Sstevel@tonic-gate 				_kobj_printf(ops, "error reading section %d\n",
24950Sstevel@tonic-gate 				    shn);
24960Sstevel@tonic-gate 				return (-1);
24970Sstevel@tonic-gate 			}
24980Sstevel@tonic-gate 			break;
24990Sstevel@tonic-gate 		}
25000Sstevel@tonic-gate 	}
25010Sstevel@tonic-gate 
25020Sstevel@tonic-gate 	/*
25030Sstevel@tonic-gate 	 * This is true for a stripped executable.  In the case of
25040Sstevel@tonic-gate 	 * 'unix' it can be stripped but it still contains the SHT_DYNSYM,
25050Sstevel@tonic-gate 	 * and since that symbol information is still present everything
25060Sstevel@tonic-gate 	 * is just fine.
25070Sstevel@tonic-gate 	 */
25080Sstevel@tonic-gate 	if (!dosymtab) {
25090Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC)
25100Sstevel@tonic-gate 			return (0);
25110Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_syms: %s ",
25123912Slling 		    mp->filename);
25130Sstevel@tonic-gate 		_kobj_printf(ops, "no SHT_SYMTAB symbol table found\n");
25140Sstevel@tonic-gate 		return (-1);
25150Sstevel@tonic-gate 	}
25160Sstevel@tonic-gate 
25170Sstevel@tonic-gate 	/*
25180Sstevel@tonic-gate 	 * get the associated string table header
25190Sstevel@tonic-gate 	 */
25200Sstevel@tonic-gate 	if ((mp->symhdr == 0) || (mp->symhdr->sh_link >= mp->hdr.e_shnum))
25210Sstevel@tonic-gate 		return (-1);
25220Sstevel@tonic-gate 	mp->strhdr = (Shdr *)
25233912Slling 	    (mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize);
25240Sstevel@tonic-gate 
25250Sstevel@tonic-gate 	mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize;
25260Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 	/*
25290Sstevel@tonic-gate 	 * Allocate space for the symbol table, buckets, chains, and strings.
25300Sstevel@tonic-gate 	 */
25310Sstevel@tonic-gate 	mp->symsize = mp->symhdr->sh_size +
25320Sstevel@tonic-gate 	    (mp->hashsize + mp->nsyms) * sizeof (symid_t) + mp->strhdr->sh_size;
25330Sstevel@tonic-gate 	mp->symspace = kobj_zalloc(mp->symsize, KM_WAIT|KM_SCRATCH);
25340Sstevel@tonic-gate 
25350Sstevel@tonic-gate 	mp->symtbl = mp->symspace;
25360Sstevel@tonic-gate 	mp->buckets = (symid_t *)(mp->symtbl + mp->symhdr->sh_size);
25370Sstevel@tonic-gate 	mp->chains = mp->buckets + mp->hashsize;
25380Sstevel@tonic-gate 	mp->strings = (char *)(mp->chains + mp->nsyms);
25390Sstevel@tonic-gate 
25400Sstevel@tonic-gate 	if (kobj_read_file(file, mp->symtbl,
25410Sstevel@tonic-gate 	    mp->symhdr->sh_size, mp->symhdr->sh_offset) < 0 ||
25420Sstevel@tonic-gate 	    kobj_read_file(file, mp->strings,
25430Sstevel@tonic-gate 	    mp->strhdr->sh_size, mp->strhdr->sh_offset) < 0)
25440Sstevel@tonic-gate 		return (-1);
25450Sstevel@tonic-gate 
25460Sstevel@tonic-gate 	/*
25470Sstevel@tonic-gate 	 * loop through the symbol table adjusting values to account
25480Sstevel@tonic-gate 	 * for where each section got loaded into memory.  Also
25490Sstevel@tonic-gate 	 * fill in the hash table.
25500Sstevel@tonic-gate 	 */
25510Sstevel@tonic-gate 	for (i = 1; i < mp->nsyms; i++) {
25520Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
25530Sstevel@tonic-gate 		if (sp->st_shndx < SHN_LORESERVE) {
25540Sstevel@tonic-gate 			if (sp->st_shndx >= mp->hdr.e_shnum) {
25550Sstevel@tonic-gate 				_kobj_printf(ops, "%s bad shndx ",
25560Sstevel@tonic-gate 				    file->_name);
25570Sstevel@tonic-gate 				_kobj_printf(ops, "in symbol %d\n", i);
25580Sstevel@tonic-gate 				return (-1);
25590Sstevel@tonic-gate 			}
25600Sstevel@tonic-gate 			shp = (Shdr *)
25610Sstevel@tonic-gate 			    (mp->shdrs +
25620Sstevel@tonic-gate 			    sp->st_shndx * mp->hdr.e_shentsize);
25630Sstevel@tonic-gate 			if (!(mp->flags & KOBJ_EXEC))
25640Sstevel@tonic-gate 				sp->st_value += shp->sh_addr;
25650Sstevel@tonic-gate 		}
25660Sstevel@tonic-gate 
25670Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
25680Sstevel@tonic-gate 			continue;
25690Sstevel@tonic-gate 		if (sp->st_name >= mp->strhdr->sh_size)
25700Sstevel@tonic-gate 			return (-1);
25710Sstevel@tonic-gate 
25720Sstevel@tonic-gate 		symname = mp->strings + sp->st_name;
25730Sstevel@tonic-gate 
25740Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_EXEC) &&
25750Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) == STB_GLOBAL) {
25760Sstevel@tonic-gate 			ksp = kobj_lookup_all(mp, symname, 0);
25770Sstevel@tonic-gate 
25780Sstevel@tonic-gate 			if (ksp && ELF_ST_BIND(ksp->st_info) == STB_GLOBAL &&
25790Sstevel@tonic-gate 			    !kobj_suppress_warning(symname) &&
25800Sstevel@tonic-gate 			    sp->st_shndx != SHN_UNDEF &&
25810Sstevel@tonic-gate 			    sp->st_shndx != SHN_COMMON &&
25820Sstevel@tonic-gate 			    ksp->st_shndx != SHN_UNDEF &&
25830Sstevel@tonic-gate 			    ksp->st_shndx != SHN_COMMON) {
25840Sstevel@tonic-gate 				/*
25850Sstevel@tonic-gate 				 * Unless this symbol is a stub, it's multiply
25860Sstevel@tonic-gate 				 * defined.  Multiply-defined symbols are
25870Sstevel@tonic-gate 				 * usually bad, but some objects (kmdb) have
25880Sstevel@tonic-gate 				 * a legitimate need to have their own
25890Sstevel@tonic-gate 				 * copies of common functions.
25900Sstevel@tonic-gate 				 */
25910Sstevel@tonic-gate 				if ((standalone ||
25920Sstevel@tonic-gate 				    ksp->st_value < (uintptr_t)stubs_base ||
25930Sstevel@tonic-gate 				    ksp->st_value >= (uintptr_t)stubs_end) &&
25940Sstevel@tonic-gate 				    !(mp->flags & KOBJ_IGNMULDEF)) {
25950Sstevel@tonic-gate 					_kobj_printf(ops,
25960Sstevel@tonic-gate 					    "%s symbol ", file->_name);
25970Sstevel@tonic-gate 					_kobj_printf(ops,
25980Sstevel@tonic-gate 					    "%s multiply defined\n", symname);
25990Sstevel@tonic-gate 				}
26000Sstevel@tonic-gate 			}
26010Sstevel@tonic-gate 		}
26023446Smrj 
26030Sstevel@tonic-gate 		sym_insert(mp, symname, i);
26040Sstevel@tonic-gate 	}
26050Sstevel@tonic-gate 
26060Sstevel@tonic-gate 	return (0);
26070Sstevel@tonic-gate }
26080Sstevel@tonic-gate 
26090Sstevel@tonic-gate static int
26100Sstevel@tonic-gate get_ctf(struct module *mp, struct _buf *file)
26110Sstevel@tonic-gate {
26120Sstevel@tonic-gate 	char *shstrtab, *ctfdata;
26130Sstevel@tonic-gate 	size_t shstrlen;
26140Sstevel@tonic-gate 	Shdr *shp;
26150Sstevel@tonic-gate 	uint_t i;
26160Sstevel@tonic-gate 
26170Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_NOCTF)
26180Sstevel@tonic-gate 		return (0); /* do not attempt to even load CTF data */
26190Sstevel@tonic-gate 
26200Sstevel@tonic-gate 	if (mp->hdr.e_shstrndx >= mp->hdr.e_shnum) {
26210Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_ctf: %s, ",
26220Sstevel@tonic-gate 		    mp->filename);
26230Sstevel@tonic-gate 		_kobj_printf(ops, "corrupt e_shstrndx %u\n",
26240Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
26250Sstevel@tonic-gate 		return (-1);
26260Sstevel@tonic-gate 	}
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate 	shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize);
26290Sstevel@tonic-gate 	shstrlen = shp->sh_size;
26300Sstevel@tonic-gate 	shstrtab = kobj_alloc(shstrlen, KM_WAIT|KM_TMP);
26310Sstevel@tonic-gate 
26320Sstevel@tonic-gate 	if (kobj_read_file(file, shstrtab, shstrlen, shp->sh_offset) < 0) {
26330Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_ctf: %s, ",
26340Sstevel@tonic-gate 		    mp->filename);
26350Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %u\n",
26360Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
26370Sstevel@tonic-gate 		kobj_free(shstrtab, shstrlen);
26380Sstevel@tonic-gate 		return (-1);
26390Sstevel@tonic-gate 	}
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 	for (i = 0; i < mp->hdr.e_shnum; i++) {
26420Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + i * mp->hdr.e_shentsize);
26430Sstevel@tonic-gate 
26440Sstevel@tonic-gate 		if (shp->sh_size != 0 && shp->sh_name < shstrlen &&
26450Sstevel@tonic-gate 		    strcmp(shstrtab + shp->sh_name, ".SUNW_ctf") == 0) {
26460Sstevel@tonic-gate 			ctfdata = kobj_alloc(shp->sh_size, KM_WAIT|KM_SCRATCH);
26470Sstevel@tonic-gate 
26480Sstevel@tonic-gate 			if (kobj_read_file(file, ctfdata, shp->sh_size,
26490Sstevel@tonic-gate 			    shp->sh_offset) < 0) {
26500Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_ctf: %s, error "
26510Sstevel@tonic-gate 				    "reading .SUNW_ctf data\n", mp->filename);
26520Sstevel@tonic-gate 				kobj_free(ctfdata, shp->sh_size);
26530Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
26540Sstevel@tonic-gate 				return (-1);
26550Sstevel@tonic-gate 			}
26560Sstevel@tonic-gate 
26570Sstevel@tonic-gate 			mp->ctfdata = ctfdata;
26580Sstevel@tonic-gate 			mp->ctfsize = shp->sh_size;
26590Sstevel@tonic-gate 			break;
26600Sstevel@tonic-gate 		}
26610Sstevel@tonic-gate 	}
26620Sstevel@tonic-gate 
26630Sstevel@tonic-gate 	kobj_free(shstrtab, shstrlen);
26640Sstevel@tonic-gate 	return (0);
26650Sstevel@tonic-gate }
26660Sstevel@tonic-gate 
26670Sstevel@tonic-gate #define	SHA1_DIGEST_LENGTH	20	/* SHA1 digest length in bytes */
26680Sstevel@tonic-gate 
26690Sstevel@tonic-gate /*
26700Sstevel@tonic-gate  * Return the hash of the ELF sections that are memory resident.
26710Sstevel@tonic-gate  * i.e. text and data.  We skip a SHT_NOBITS section since it occupies
26720Sstevel@tonic-gate  * no space in the file. We use SHA1 here since libelfsign uses
26730Sstevel@tonic-gate  * it and both places need to use the same algorithm.
26740Sstevel@tonic-gate  */
26750Sstevel@tonic-gate static void
26760Sstevel@tonic-gate crypto_es_hash(struct module *mp, char *hash, char *shstrtab)
26770Sstevel@tonic-gate {
26780Sstevel@tonic-gate 	uint_t shn;
26790Sstevel@tonic-gate 	Shdr *shp;
26800Sstevel@tonic-gate 	SHA1_CTX ctx;
26810Sstevel@tonic-gate 
26820Sstevel@tonic-gate 	SHA1Init(&ctx);
26830Sstevel@tonic-gate 
26840Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
26850Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
26860Sstevel@tonic-gate 		if (!(shp->sh_flags & SHF_ALLOC) || shp->sh_size == 0)
26870Sstevel@tonic-gate 			continue;
26880Sstevel@tonic-gate 
26890Sstevel@tonic-gate 		/*
26900Sstevel@tonic-gate 		 * The check should ideally be shp->sh_type == SHT_NOBITS.
26910Sstevel@tonic-gate 		 * However, we can't do that check here as get_progbits()
26920Sstevel@tonic-gate 		 * resets the type.
26930Sstevel@tonic-gate 		 */
26940Sstevel@tonic-gate 		if (strcmp(shstrtab + shp->sh_name, ".bss") == 0)
26950Sstevel@tonic-gate 			continue;
26960Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
26970Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG)
26980Sstevel@tonic-gate 			_kobj_printf(ops,
26990Sstevel@tonic-gate 			    "krtld: crypto_es_hash: updating hash with"
27000Sstevel@tonic-gate 			    " %s data size=%d\n", shstrtab + shp->sh_name,
27013912Slling 			    shp->sh_size);
27020Sstevel@tonic-gate #endif
27030Sstevel@tonic-gate 		ASSERT(shp->sh_addr != NULL);
27040Sstevel@tonic-gate 		SHA1Update(&ctx, (const uint8_t *)shp->sh_addr, shp->sh_size);
27050Sstevel@tonic-gate 	}
27060Sstevel@tonic-gate 
27070Sstevel@tonic-gate 	SHA1Final((uchar_t *)hash, &ctx);
27080Sstevel@tonic-gate }
27090Sstevel@tonic-gate 
27100Sstevel@tonic-gate /*
27110Sstevel@tonic-gate  * Get the .SUNW_signature section for the module, it it exists.
27120Sstevel@tonic-gate  *
27130Sstevel@tonic-gate  * This section exists only for crypto modules. None of the
27140Sstevel@tonic-gate  * primary modules have this section currently.
27150Sstevel@tonic-gate  */
27160Sstevel@tonic-gate static void
27170Sstevel@tonic-gate get_signature(struct module *mp, struct _buf *file)
27180Sstevel@tonic-gate {
27190Sstevel@tonic-gate 	char *shstrtab, *sigdata = NULL;
27200Sstevel@tonic-gate 	size_t shstrlen;
27210Sstevel@tonic-gate 	Shdr *shp;
27220Sstevel@tonic-gate 	uint_t i;
27230Sstevel@tonic-gate 
27240Sstevel@tonic-gate 	if (mp->hdr.e_shstrndx >= mp->hdr.e_shnum) {
27250Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_signature: %s, ",
27260Sstevel@tonic-gate 		    mp->filename);
27270Sstevel@tonic-gate 		_kobj_printf(ops, "corrupt e_shstrndx %u\n",
27280Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
27290Sstevel@tonic-gate 		return;
27300Sstevel@tonic-gate 	}
27310Sstevel@tonic-gate 
27320Sstevel@tonic-gate 	shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize);
27330Sstevel@tonic-gate 	shstrlen = shp->sh_size;
27340Sstevel@tonic-gate 	shstrtab = kobj_alloc(shstrlen, KM_WAIT|KM_TMP);
27350Sstevel@tonic-gate 
27360Sstevel@tonic-gate 	if (kobj_read_file(file, shstrtab, shstrlen, shp->sh_offset) < 0) {
27370Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_signature: %s, ",
27380Sstevel@tonic-gate 		    mp->filename);
27390Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %u\n",
27400Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
27410Sstevel@tonic-gate 		kobj_free(shstrtab, shstrlen);
27420Sstevel@tonic-gate 		return;
27430Sstevel@tonic-gate 	}
27440Sstevel@tonic-gate 
27450Sstevel@tonic-gate 	for (i = 0; i < mp->hdr.e_shnum; i++) {
27460Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + i * mp->hdr.e_shentsize);
27470Sstevel@tonic-gate 		if (shp->sh_size != 0 && shp->sh_name < shstrlen &&
27480Sstevel@tonic-gate 		    strcmp(shstrtab + shp->sh_name,
27490Sstevel@tonic-gate 		    ELF_SIGNATURE_SECTION) == 0) {
27500Sstevel@tonic-gate 			filesig_vers_t filesig_version;
27510Sstevel@tonic-gate 			size_t sigsize = shp->sh_size + SHA1_DIGEST_LENGTH;
27520Sstevel@tonic-gate 			sigdata = kobj_alloc(sigsize, KM_WAIT|KM_SCRATCH);
27530Sstevel@tonic-gate 
27540Sstevel@tonic-gate 			if (kobj_read_file(file, sigdata, shp->sh_size,
27550Sstevel@tonic-gate 			    shp->sh_offset) < 0) {
27560Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_signature: %s,"
27570Sstevel@tonic-gate 				    " error reading .SUNW_signature data\n",
27580Sstevel@tonic-gate 				    mp->filename);
27590Sstevel@tonic-gate 				kobj_free(sigdata, sigsize);
27600Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
27610Sstevel@tonic-gate 				return;
27620Sstevel@tonic-gate 			}
27630Sstevel@tonic-gate 			filesig_version = ((struct filesignatures *)sigdata)->
27640Sstevel@tonic-gate 			    filesig_sig.filesig_version;
27650Sstevel@tonic-gate 			if (!(filesig_version == FILESIG_VERSION1 ||
27660Sstevel@tonic-gate 			    filesig_version == FILESIG_VERSION3)) {
27670Sstevel@tonic-gate 				/* skip versions we don't understand */
27680Sstevel@tonic-gate 				kobj_free(sigdata, sigsize);
27690Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
27700Sstevel@tonic-gate 				return;
27710Sstevel@tonic-gate 			}
27720Sstevel@tonic-gate 
27730Sstevel@tonic-gate 			mp->sigdata = sigdata;
27740Sstevel@tonic-gate 			mp->sigsize = sigsize;
27750Sstevel@tonic-gate 			break;
27760Sstevel@tonic-gate 		}
27770Sstevel@tonic-gate 	}
27780Sstevel@tonic-gate 
27790Sstevel@tonic-gate 	if (sigdata != NULL) {
27800Sstevel@tonic-gate 		crypto_es_hash(mp, sigdata + shp->sh_size, shstrtab);
27810Sstevel@tonic-gate 	}
27820Sstevel@tonic-gate 
27830Sstevel@tonic-gate 	kobj_free(shstrtab, shstrlen);
27840Sstevel@tonic-gate }
27850Sstevel@tonic-gate 
27860Sstevel@tonic-gate static void
27870Sstevel@tonic-gate add_dependent(struct module *mp, struct module *dep)
27880Sstevel@tonic-gate {
27890Sstevel@tonic-gate 	struct module_list *lp;
27900Sstevel@tonic-gate 
27910Sstevel@tonic-gate 	for (lp = mp->head; lp; lp = lp->next) {
27920Sstevel@tonic-gate 		if (lp->mp == dep)
27930Sstevel@tonic-gate 			return;	/* already on the list */
27940Sstevel@tonic-gate 	}
27950Sstevel@tonic-gate 
27960Sstevel@tonic-gate 	if (lp == NULL) {
27970Sstevel@tonic-gate 		lp = kobj_zalloc(sizeof (*lp), KM_WAIT);
27980Sstevel@tonic-gate 
27990Sstevel@tonic-gate 		lp->mp = dep;
28000Sstevel@tonic-gate 		lp->next = NULL;
28010Sstevel@tonic-gate 		if (mp->tail)
28020Sstevel@tonic-gate 			mp->tail->next = lp;
28030Sstevel@tonic-gate 		else
28040Sstevel@tonic-gate 			mp->head = lp;
28050Sstevel@tonic-gate 		mp->tail = lp;
28060Sstevel@tonic-gate 	}
28070Sstevel@tonic-gate }
28080Sstevel@tonic-gate 
28090Sstevel@tonic-gate static int
28100Sstevel@tonic-gate do_dependents(struct modctl *modp, char *modname, size_t modnamelen)
28110Sstevel@tonic-gate {
28120Sstevel@tonic-gate 	struct module *mp;
28130Sstevel@tonic-gate 	struct modctl *req;
28140Sstevel@tonic-gate 	char *d, *p, *q;
28150Sstevel@tonic-gate 	int c;
28160Sstevel@tonic-gate 	char *err_modname = NULL;
28170Sstevel@tonic-gate 
28180Sstevel@tonic-gate 	mp = modp->mod_mp;
28190Sstevel@tonic-gate 
28200Sstevel@tonic-gate 	if ((p = mp->depends_on) == NULL)
28210Sstevel@tonic-gate 		return (0);
28220Sstevel@tonic-gate 
28230Sstevel@tonic-gate 	for (;;) {
28240Sstevel@tonic-gate 		/*
28250Sstevel@tonic-gate 		 * Skip space.
28260Sstevel@tonic-gate 		 */
28270Sstevel@tonic-gate 		while (*p && (*p == ' ' || *p == '\t'))
28280Sstevel@tonic-gate 			p++;
28290Sstevel@tonic-gate 		/*
28300Sstevel@tonic-gate 		 * Get module name.
28310Sstevel@tonic-gate 		 */
28320Sstevel@tonic-gate 		d = p;
28330Sstevel@tonic-gate 		q = modname;
28340Sstevel@tonic-gate 		c = 0;
28350Sstevel@tonic-gate 		while (*p && *p != ' ' && *p != '\t') {
28360Sstevel@tonic-gate 			if (c < modnamelen - 1) {
28370Sstevel@tonic-gate 				*q++ = *p;
28380Sstevel@tonic-gate 				c++;
28390Sstevel@tonic-gate 			}
28400Sstevel@tonic-gate 			p++;
28410Sstevel@tonic-gate 		}
28420Sstevel@tonic-gate 
28430Sstevel@tonic-gate 		if (q == modname)
28440Sstevel@tonic-gate 			break;
28450Sstevel@tonic-gate 
28460Sstevel@tonic-gate 		if (c == modnamelen - 1) {
28470Sstevel@tonic-gate 			char *dep = kobj_alloc(p - d + 1, KM_WAIT|KM_TMP);
28480Sstevel@tonic-gate 
28490Sstevel@tonic-gate 			(void) strncpy(dep, d,  p - d + 1);
28500Sstevel@tonic-gate 			dep[p - d] = '\0';
28510Sstevel@tonic-gate 
28520Sstevel@tonic-gate 			_kobj_printf(ops, "%s: dependency ", modp->mod_modname);
28530Sstevel@tonic-gate 			_kobj_printf(ops, "'%s' too long ", dep);
28540Sstevel@tonic-gate 			_kobj_printf(ops, "(max %d chars)\n", modnamelen);
28550Sstevel@tonic-gate 
28560Sstevel@tonic-gate 			kobj_free(dep, p - d + 1);
28570Sstevel@tonic-gate 
28580Sstevel@tonic-gate 			return (-1);
28590Sstevel@tonic-gate 		}
28600Sstevel@tonic-gate 
28610Sstevel@tonic-gate 		*q = '\0';
28620Sstevel@tonic-gate 		if ((req = mod_load_requisite(modp, modname)) == NULL) {
28630Sstevel@tonic-gate #ifndef	KOBJ_DEBUG
28640Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_LOADMSG) {
28650Sstevel@tonic-gate #endif	/* KOBJ_DEBUG */
28660Sstevel@tonic-gate 				_kobj_printf(ops,
28670Sstevel@tonic-gate 				    "%s: unable to resolve dependency, ",
28680Sstevel@tonic-gate 				    modp->mod_modname);
28690Sstevel@tonic-gate 				_kobj_printf(ops, "cannot load module '%s'\n",
28700Sstevel@tonic-gate 				    modname);
28710Sstevel@tonic-gate #ifndef	KOBJ_DEBUG
28720Sstevel@tonic-gate 			}
28730Sstevel@tonic-gate #endif	/* KOBJ_DEBUG */
28740Sstevel@tonic-gate 			if (err_modname == NULL) {
28750Sstevel@tonic-gate 				/*
28760Sstevel@tonic-gate 				 * This must be the same size as the modname
28770Sstevel@tonic-gate 				 * one.
28780Sstevel@tonic-gate 				 */
28790Sstevel@tonic-gate 				err_modname = kobj_zalloc(MODMAXNAMELEN,
28800Sstevel@tonic-gate 				    KM_WAIT);
28810Sstevel@tonic-gate 
28820Sstevel@tonic-gate 				/*
28830Sstevel@tonic-gate 				 * We can use strcpy() here without fearing
28840Sstevel@tonic-gate 				 * the NULL terminator because the size of
28850Sstevel@tonic-gate 				 * err_modname is the same as one of modname,
28860Sstevel@tonic-gate 				 * and it's filled with zeros.
28870Sstevel@tonic-gate 				 */
28880Sstevel@tonic-gate 				(void) strcpy(err_modname, modname);
28890Sstevel@tonic-gate 			}
28900Sstevel@tonic-gate 			continue;
28910Sstevel@tonic-gate 		}
28920Sstevel@tonic-gate 
28930Sstevel@tonic-gate 		add_dependent(mp, req->mod_mp);
28940Sstevel@tonic-gate 		mod_release_mod(req);
28950Sstevel@tonic-gate 
28960Sstevel@tonic-gate 	}
28970Sstevel@tonic-gate 
28980Sstevel@tonic-gate 	if (err_modname != NULL) {
28990Sstevel@tonic-gate 		/*
29000Sstevel@tonic-gate 		 * Copy the first module name where you detect an error to keep
29010Sstevel@tonic-gate 		 * its behavior the same as before.
29020Sstevel@tonic-gate 		 * This way keeps minimizing the memory use for error
29030Sstevel@tonic-gate 		 * modules, and this might be important at boot time because
29040Sstevel@tonic-gate 		 * the memory usage is a crucial factor for booting in most
29050Sstevel@tonic-gate 		 * cases. You can expect more verbose messages when using
29060Sstevel@tonic-gate 		 * a debug kernel or setting a bit in moddebug.
29070Sstevel@tonic-gate 		 */
29080Sstevel@tonic-gate 		bzero(modname, MODMAXNAMELEN);
29090Sstevel@tonic-gate 		(void) strcpy(modname, err_modname);
29100Sstevel@tonic-gate 		kobj_free(err_modname, MODMAXNAMELEN);
29110Sstevel@tonic-gate 		return (-1);
29120Sstevel@tonic-gate 	}
29130Sstevel@tonic-gate 
29140Sstevel@tonic-gate 	return (0);
29150Sstevel@tonic-gate }
29160Sstevel@tonic-gate 
29170Sstevel@tonic-gate static int
29180Sstevel@tonic-gate do_common(struct module *mp)
29190Sstevel@tonic-gate {
29200Sstevel@tonic-gate 	int err;
29210Sstevel@tonic-gate 
29220Sstevel@tonic-gate 	/*
29230Sstevel@tonic-gate 	 * first time through, assign all symbols defined in other
29240Sstevel@tonic-gate 	 * modules, and count up how much common space will be needed
29250Sstevel@tonic-gate 	 * (bss_size and bss_align)
29260Sstevel@tonic-gate 	 */
29270Sstevel@tonic-gate 	if ((err = do_symbols(mp, 0)) < 0)
29280Sstevel@tonic-gate 		return (err);
29290Sstevel@tonic-gate 	/*
29300Sstevel@tonic-gate 	 * increase bss_size by the maximum delta that could be
29310Sstevel@tonic-gate 	 * computed by the ALIGN below
29320Sstevel@tonic-gate 	 */
29330Sstevel@tonic-gate 	mp->bss_size += mp->bss_align;
29340Sstevel@tonic-gate 	if (mp->bss_size) {
29350Sstevel@tonic-gate 		if (standalone)
29360Sstevel@tonic-gate 			mp->bss = (uintptr_t)kobj_segbrk(&_edata, mp->bss_size,
29370Sstevel@tonic-gate 			    MINALIGN, 0);
29380Sstevel@tonic-gate 		else
29390Sstevel@tonic-gate 			mp->bss = (uintptr_t)vmem_alloc(data_arena,
29400Sstevel@tonic-gate 			    mp->bss_size, VM_SLEEP | VM_BESTFIT);
29410Sstevel@tonic-gate 		bzero((void *)mp->bss, mp->bss_size);
29420Sstevel@tonic-gate 		/* now assign addresses to all common symbols */
29430Sstevel@tonic-gate 		if ((err = do_symbols(mp, ALIGN(mp->bss, mp->bss_align))) < 0)
29440Sstevel@tonic-gate 			return (err);
29450Sstevel@tonic-gate 	}
29460Sstevel@tonic-gate 	return (0);
29470Sstevel@tonic-gate }
29480Sstevel@tonic-gate 
29490Sstevel@tonic-gate static int
29500Sstevel@tonic-gate do_symbols(struct module *mp, Elf64_Addr bss_base)
29510Sstevel@tonic-gate {
29520Sstevel@tonic-gate 	int bss_align;
29530Sstevel@tonic-gate 	uintptr_t bss_ptr;
29540Sstevel@tonic-gate 	int err;
29550Sstevel@tonic-gate 	int i;
29560Sstevel@tonic-gate 	Sym *sp, *sp1;
29570Sstevel@tonic-gate 	char *name;
29580Sstevel@tonic-gate 	int assign;
29590Sstevel@tonic-gate 	int resolved = 1;
29600Sstevel@tonic-gate 
29610Sstevel@tonic-gate 	/*
29620Sstevel@tonic-gate 	 * Nothing left to do (optimization).
29630Sstevel@tonic-gate 	 */
29640Sstevel@tonic-gate 	if (mp->flags & KOBJ_RESOLVED)
29650Sstevel@tonic-gate 		return (0);
29660Sstevel@tonic-gate 
29670Sstevel@tonic-gate 	assign = (bss_base) ? 1 : 0;
29680Sstevel@tonic-gate 	bss_ptr = bss_base;
29690Sstevel@tonic-gate 	bss_align = 0;
29700Sstevel@tonic-gate 	err = 0;
29710Sstevel@tonic-gate 
29720Sstevel@tonic-gate 	for (i = 1; i < mp->nsyms; i++) {
29730Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + mp->symhdr->sh_entsize * i);
29740Sstevel@tonic-gate 		/*
29750Sstevel@tonic-gate 		 * we know that st_name is in bounds, since get_sections
29760Sstevel@tonic-gate 		 * has already checked all of the symbols
29770Sstevel@tonic-gate 		 */
29780Sstevel@tonic-gate 		name = mp->strings + sp->st_name;
29790Sstevel@tonic-gate 		if (sp->st_shndx != SHN_UNDEF && sp->st_shndx != SHN_COMMON)
29800Sstevel@tonic-gate 			continue;
29815648Ssetje #if defined(__sparc)
29820Sstevel@tonic-gate 		/*
29830Sstevel@tonic-gate 		 * Register symbols are ignored in the kernel
29840Sstevel@tonic-gate 		 */
29850Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_SPARC_REGISTER) {
29860Sstevel@tonic-gate 			if (*name != '\0') {
29870Sstevel@tonic-gate 				_kobj_printf(ops, "%s: named REGISTER symbol ",
29883912Slling 				    mp->filename);
29890Sstevel@tonic-gate 				_kobj_printf(ops, "not supported '%s'\n",
29903912Slling 				    name);
29910Sstevel@tonic-gate 				err = DOSYM_UNDEF;
29920Sstevel@tonic-gate 			}
29930Sstevel@tonic-gate 			continue;
29940Sstevel@tonic-gate 		}
29950Sstevel@tonic-gate #endif	/* __sparc */
29960Sstevel@tonic-gate 		/*
29970Sstevel@tonic-gate 		 * TLS symbols are ignored in the kernel
29980Sstevel@tonic-gate 		 */
29990Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_TLS) {
30000Sstevel@tonic-gate 			_kobj_printf(ops, "%s: TLS symbol ",
30013912Slling 			    mp->filename);
30020Sstevel@tonic-gate 			_kobj_printf(ops, "not supported '%s'\n",
30033912Slling 			    name);
30040Sstevel@tonic-gate 			err = DOSYM_UNDEF;
30050Sstevel@tonic-gate 			continue;
30060Sstevel@tonic-gate 		}
30070Sstevel@tonic-gate 
30080Sstevel@tonic-gate 		if (ELF_ST_BIND(sp->st_info) != STB_LOCAL) {
30090Sstevel@tonic-gate 			if ((sp1 = kobj_lookup_all(mp, name, 0)) != NULL) {
30100Sstevel@tonic-gate 				sp->st_shndx = SHN_ABS;
30110Sstevel@tonic-gate 				sp->st_value = sp1->st_value;
30120Sstevel@tonic-gate 				continue;
30130Sstevel@tonic-gate 			}
30140Sstevel@tonic-gate 		}
30150Sstevel@tonic-gate 
30160Sstevel@tonic-gate 		if (sp->st_shndx == SHN_UNDEF) {
30170Sstevel@tonic-gate 			resolved = 0;
30180Sstevel@tonic-gate 
30190Sstevel@tonic-gate 			if (strncmp(name, sdt_prefix, strlen(sdt_prefix)) == 0)
30200Sstevel@tonic-gate 				continue;
30210Sstevel@tonic-gate 
30220Sstevel@tonic-gate 			/*
30230Sstevel@tonic-gate 			 * If it's not a weak reference and it's
30240Sstevel@tonic-gate 			 * not a primary object, it's an error.
30250Sstevel@tonic-gate 			 * (Primary objects may take more than
30260Sstevel@tonic-gate 			 * one pass to resolve)
30270Sstevel@tonic-gate 			 */
30280Sstevel@tonic-gate 			if (!(mp->flags & KOBJ_PRIM) &&
30290Sstevel@tonic-gate 			    ELF_ST_BIND(sp->st_info) != STB_WEAK) {
30300Sstevel@tonic-gate 				_kobj_printf(ops, "%s: undefined symbol",
30310Sstevel@tonic-gate 				    mp->filename);
30320Sstevel@tonic-gate 				_kobj_printf(ops, " '%s'\n", name);
30330Sstevel@tonic-gate 				/*
30340Sstevel@tonic-gate 				 * Try to determine whether this symbol
30350Sstevel@tonic-gate 				 * represents a dependency on obsolete
30360Sstevel@tonic-gate 				 * unsafe driver support.  This is just
30370Sstevel@tonic-gate 				 * to make the warning more informative.
30380Sstevel@tonic-gate 				 */
30390Sstevel@tonic-gate 				if (strcmp(name, "sleep") == 0 ||
30400Sstevel@tonic-gate 				    strcmp(name, "unsleep") == 0 ||
30410Sstevel@tonic-gate 				    strcmp(name, "wakeup") == 0 ||
30420Sstevel@tonic-gate 				    strcmp(name, "bsd_compat_ioctl") == 0 ||
30430Sstevel@tonic-gate 				    strcmp(name, "unsafe_driver") == 0 ||
30440Sstevel@tonic-gate 				    strncmp(name, "spl", 3) == 0 ||
30450Sstevel@tonic-gate 				    strncmp(name, "i_ddi_spl", 9) == 0)
30460Sstevel@tonic-gate 					err = DOSYM_UNSAFE;
30470Sstevel@tonic-gate 				if (err == 0)
30480Sstevel@tonic-gate 					err = DOSYM_UNDEF;
30490Sstevel@tonic-gate 			}
30500Sstevel@tonic-gate 			continue;
30510Sstevel@tonic-gate 		}
30520Sstevel@tonic-gate 		/*
30530Sstevel@tonic-gate 		 * It's a common symbol - st_value is the
30540Sstevel@tonic-gate 		 * required alignment.
30550Sstevel@tonic-gate 		 */
30560Sstevel@tonic-gate 		if (sp->st_value > bss_align)
30570Sstevel@tonic-gate 			bss_align = sp->st_value;
30580Sstevel@tonic-gate 		bss_ptr = ALIGN(bss_ptr, sp->st_value);
30590Sstevel@tonic-gate 		if (assign) {
30600Sstevel@tonic-gate 			sp->st_shndx = SHN_ABS;
30610Sstevel@tonic-gate 			sp->st_value = bss_ptr;
30620Sstevel@tonic-gate 		}
30630Sstevel@tonic-gate 		bss_ptr += sp->st_size;
30640Sstevel@tonic-gate 	}
30650Sstevel@tonic-gate 	if (err)
30660Sstevel@tonic-gate 		return (err);
30670Sstevel@tonic-gate 	if (assign == 0 && mp->bss == NULL) {
30680Sstevel@tonic-gate 		mp->bss_align = bss_align;
30690Sstevel@tonic-gate 		mp->bss_size = bss_ptr;
30700Sstevel@tonic-gate 	} else if (resolved) {
30710Sstevel@tonic-gate 		mp->flags |= KOBJ_RESOLVED;
30720Sstevel@tonic-gate 	}
30730Sstevel@tonic-gate 
30740Sstevel@tonic-gate 	return (0);
30750Sstevel@tonic-gate }
30760Sstevel@tonic-gate 
30770Sstevel@tonic-gate uint_t
30780Sstevel@tonic-gate kobj_hash_name(const char *p)
30790Sstevel@tonic-gate {
30805648Ssetje 	uint_t g;
30810Sstevel@tonic-gate 	uint_t hval;
30820Sstevel@tonic-gate 
30830Sstevel@tonic-gate 	hval = 0;
30840Sstevel@tonic-gate 	while (*p) {
30850Sstevel@tonic-gate 		hval = (hval << 4) + *p++;
30860Sstevel@tonic-gate 		if ((g = (hval & 0xf0000000)) != 0)
30870Sstevel@tonic-gate 			hval ^= g >> 24;
30880Sstevel@tonic-gate 		hval &= ~g;
30890Sstevel@tonic-gate 	}
30900Sstevel@tonic-gate 	return (hval);
30910Sstevel@tonic-gate }
30920Sstevel@tonic-gate 
30930Sstevel@tonic-gate /* look for name in all modules */
30940Sstevel@tonic-gate uintptr_t
30950Sstevel@tonic-gate kobj_getsymvalue(char *name, int kernelonly)
30960Sstevel@tonic-gate {
30970Sstevel@tonic-gate 	Sym		*sp;
30980Sstevel@tonic-gate 	struct modctl	*modp;
30990Sstevel@tonic-gate 	struct module	*mp;
31000Sstevel@tonic-gate 	uintptr_t	value = 0;
31010Sstevel@tonic-gate 
31020Sstevel@tonic-gate 	if ((sp = kobj_lookup_kernel(name)) != NULL)
31030Sstevel@tonic-gate 		return ((uintptr_t)sp->st_value);
31040Sstevel@tonic-gate 
31050Sstevel@tonic-gate 	if (kernelonly)
31060Sstevel@tonic-gate 		return (0);	/* didn't find it in the kernel so give up */
31070Sstevel@tonic-gate 
31080Sstevel@tonic-gate 	mutex_enter(&mod_lock);
31090Sstevel@tonic-gate 	modp = &modules;
31100Sstevel@tonic-gate 	do {
31110Sstevel@tonic-gate 		mp = (struct module *)modp->mod_mp;
31120Sstevel@tonic-gate 		if (mp && !(mp->flags & KOBJ_PRIM) && modp->mod_loaded &&
31130Sstevel@tonic-gate 		    (sp = lookup_one(mp, name))) {
31140Sstevel@tonic-gate 			value = (uintptr_t)sp->st_value;
31150Sstevel@tonic-gate 			break;
31160Sstevel@tonic-gate 		}
31170Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
31180Sstevel@tonic-gate 	mutex_exit(&mod_lock);
31190Sstevel@tonic-gate 	return (value);
31200Sstevel@tonic-gate }
31210Sstevel@tonic-gate 
31220Sstevel@tonic-gate /* look for a symbol near value. */
31230Sstevel@tonic-gate char *
31240Sstevel@tonic-gate kobj_getsymname(uintptr_t value, ulong_t *offset)
31250Sstevel@tonic-gate {
31260Sstevel@tonic-gate 	char *name = NULL;
31270Sstevel@tonic-gate 	struct modctl *modp;
31280Sstevel@tonic-gate 
31290Sstevel@tonic-gate 	struct modctl_list *lp;
31300Sstevel@tonic-gate 	struct module *mp;
31310Sstevel@tonic-gate 
31320Sstevel@tonic-gate 	/*
31330Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
31340Sstevel@tonic-gate 	 */
31350Sstevel@tonic-gate 	for (lp = kobj_lm_lookup(KOBJ_LM_PRIMARY); lp; lp = lp->modl_next) {
31360Sstevel@tonic-gate 		mp = mod(lp);
31370Sstevel@tonic-gate 
31380Sstevel@tonic-gate 		if ((name = kobj_searchsym(mp, value, offset)) != NULL)
31390Sstevel@tonic-gate 			return (name);
31400Sstevel@tonic-gate 	}
31410Sstevel@tonic-gate 
31420Sstevel@tonic-gate 	mutex_enter(&mod_lock);
31430Sstevel@tonic-gate 	modp = &modules;
31440Sstevel@tonic-gate 	do {
31450Sstevel@tonic-gate 		mp = (struct module *)modp->mod_mp;
31460Sstevel@tonic-gate 		if (mp && !(mp->flags & KOBJ_PRIM) && modp->mod_loaded &&
31470Sstevel@tonic-gate 		    (name = kobj_searchsym(mp, value, offset)))
31480Sstevel@tonic-gate 			break;
31490Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
31500Sstevel@tonic-gate 	mutex_exit(&mod_lock);
31510Sstevel@tonic-gate 	return (name);
31520Sstevel@tonic-gate }
31530Sstevel@tonic-gate 
31540Sstevel@tonic-gate /* return address of symbol and size */
31550Sstevel@tonic-gate 
31560Sstevel@tonic-gate uintptr_t
31570Sstevel@tonic-gate kobj_getelfsym(char *name, void *mp, int *size)
31580Sstevel@tonic-gate {
31590Sstevel@tonic-gate 	Sym *sp;
31600Sstevel@tonic-gate 
31610Sstevel@tonic-gate 	if (mp == NULL)
31620Sstevel@tonic-gate 		sp = kobj_lookup_kernel(name);
31630Sstevel@tonic-gate 	else
31640Sstevel@tonic-gate 		sp = lookup_one(mp, name);
31650Sstevel@tonic-gate 
31660Sstevel@tonic-gate 	if (sp == NULL)
31670Sstevel@tonic-gate 		return (0);
31680Sstevel@tonic-gate 
31690Sstevel@tonic-gate 	*size = (int)sp->st_size;
31700Sstevel@tonic-gate 	return ((uintptr_t)sp->st_value);
31710Sstevel@tonic-gate }
31720Sstevel@tonic-gate 
31730Sstevel@tonic-gate uintptr_t
31741414Scindi kobj_lookup(struct module *mod, const char *name)
31750Sstevel@tonic-gate {
31760Sstevel@tonic-gate 	Sym *sp;
31770Sstevel@tonic-gate 
31780Sstevel@tonic-gate 	sp = lookup_one(mod, name);
31790Sstevel@tonic-gate 
31800Sstevel@tonic-gate 	if (sp == NULL)
31810Sstevel@tonic-gate 		return (0);
31820Sstevel@tonic-gate 
31830Sstevel@tonic-gate 	return ((uintptr_t)sp->st_value);
31840Sstevel@tonic-gate }
31850Sstevel@tonic-gate 
31860Sstevel@tonic-gate char *
31870Sstevel@tonic-gate kobj_searchsym(struct module *mp, uintptr_t value, ulong_t *offset)
31880Sstevel@tonic-gate {
31890Sstevel@tonic-gate 	Sym *symtabptr;
31900Sstevel@tonic-gate 	char *strtabptr;
31910Sstevel@tonic-gate 	int symnum;
31920Sstevel@tonic-gate 	Sym *sym;
31930Sstevel@tonic-gate 	Sym *cursym;
31940Sstevel@tonic-gate 	uintptr_t curval;
31950Sstevel@tonic-gate 
31960Sstevel@tonic-gate 	*offset = (ulong_t)-1l;		/* assume not found */
31970Sstevel@tonic-gate 	cursym  = NULL;
31980Sstevel@tonic-gate 
31990Sstevel@tonic-gate 	if (kobj_addrcheck(mp, (void *)value) != 0)
32000Sstevel@tonic-gate 		return (NULL);		/* not in this module */
32010Sstevel@tonic-gate 
32020Sstevel@tonic-gate 	strtabptr  = mp->strings;
32030Sstevel@tonic-gate 	symtabptr  = (Sym *)mp->symtbl;
32040Sstevel@tonic-gate 
32050Sstevel@tonic-gate 	/*
32060Sstevel@tonic-gate 	 * Scan the module's symbol table for a symbol <= value
32070Sstevel@tonic-gate 	 */
32080Sstevel@tonic-gate 	for (symnum = 1, sym = symtabptr + 1;
32090Sstevel@tonic-gate 	    symnum < mp->nsyms; symnum++, sym = (Sym *)
32100Sstevel@tonic-gate 	    ((uintptr_t)sym + mp->symhdr->sh_entsize)) {
32110Sstevel@tonic-gate 		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) {
32120Sstevel@tonic-gate 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
32130Sstevel@tonic-gate 				continue;
32140Sstevel@tonic-gate 			if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
32150Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info) != STT_FUNC)
32160Sstevel@tonic-gate 				continue;
32170Sstevel@tonic-gate 		}
32180Sstevel@tonic-gate 
32190Sstevel@tonic-gate 		curval = (uintptr_t)sym->st_value;
32200Sstevel@tonic-gate 
32210Sstevel@tonic-gate 		if (curval > value)
32220Sstevel@tonic-gate 			continue;
32230Sstevel@tonic-gate 
32240Sstevel@tonic-gate 		/*
32250Sstevel@tonic-gate 		 * If one or both are functions...
32260Sstevel@tonic-gate 		 */
32270Sstevel@tonic-gate 		if (ELF_ST_TYPE(sym->st_info) == STT_FUNC || (cursym != NULL &&
32280Sstevel@tonic-gate 		    ELF_ST_TYPE(cursym->st_info) == STT_FUNC)) {
32290Sstevel@tonic-gate 			/* Ignore if the address is out of the bounds */
32300Sstevel@tonic-gate 			if (value - sym->st_value >= sym->st_size)
32310Sstevel@tonic-gate 				continue;
32320Sstevel@tonic-gate 
32330Sstevel@tonic-gate 			if (cursym != NULL &&
32340Sstevel@tonic-gate 			    ELF_ST_TYPE(cursym->st_info) == STT_FUNC) {
32350Sstevel@tonic-gate 				/* Prefer the function to the non-function */
32360Sstevel@tonic-gate 				if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
32370Sstevel@tonic-gate 					continue;
32380Sstevel@tonic-gate 
32390Sstevel@tonic-gate 				/* Prefer the larger of the two functions */
32400Sstevel@tonic-gate 				if (sym->st_size <= cursym->st_size)
32410Sstevel@tonic-gate 					continue;
32420Sstevel@tonic-gate 			}
32430Sstevel@tonic-gate 		} else if (value - curval >= *offset) {
32440Sstevel@tonic-gate 			continue;
32450Sstevel@tonic-gate 		}
32460Sstevel@tonic-gate 
32470Sstevel@tonic-gate 		*offset = (ulong_t)(value - curval);
32480Sstevel@tonic-gate 		cursym = sym;
32490Sstevel@tonic-gate 	}
32500Sstevel@tonic-gate 	if (cursym == NULL)
32510Sstevel@tonic-gate 		return (NULL);
32520Sstevel@tonic-gate 
32530Sstevel@tonic-gate 	return (strtabptr + cursym->st_name);
32540Sstevel@tonic-gate }
32550Sstevel@tonic-gate 
32560Sstevel@tonic-gate Sym *
32570Sstevel@tonic-gate kobj_lookup_all(struct module *mp, char *name, int include_self)
32580Sstevel@tonic-gate {
32590Sstevel@tonic-gate 	Sym *sp;
32600Sstevel@tonic-gate 	struct module_list *mlp;
32610Sstevel@tonic-gate 	struct modctl_list *clp;
32620Sstevel@tonic-gate 	struct module *mmp;
32630Sstevel@tonic-gate 
32640Sstevel@tonic-gate 	if (include_self && (sp = lookup_one(mp, name)) != NULL)
32650Sstevel@tonic-gate 		return (sp);
32660Sstevel@tonic-gate 
32670Sstevel@tonic-gate 	for (mlp = mp->head; mlp; mlp = mlp->next) {
32680Sstevel@tonic-gate 		if ((sp = lookup_one(mlp->mp, name)) != NULL &&
32690Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) != STB_LOCAL)
32700Sstevel@tonic-gate 			return (sp);
32710Sstevel@tonic-gate 	}
32720Sstevel@tonic-gate 
32730Sstevel@tonic-gate 	/*
32740Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
32750Sstevel@tonic-gate 	 */
32760Sstevel@tonic-gate 	for (clp = kobj_lm_lookup(KOBJ_LM_PRIMARY); clp; clp = clp->modl_next) {
32770Sstevel@tonic-gate 		mmp = mod(clp);
32780Sstevel@tonic-gate 
32790Sstevel@tonic-gate 		if (mmp == NULL || mp == mmp)
32800Sstevel@tonic-gate 			continue;
32810Sstevel@tonic-gate 
32820Sstevel@tonic-gate 		if ((sp = lookup_one(mmp, name)) != NULL &&
32830Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) != STB_LOCAL)
32840Sstevel@tonic-gate 			return (sp);
32850Sstevel@tonic-gate 	}
32860Sstevel@tonic-gate 	return (NULL);
32870Sstevel@tonic-gate }
32880Sstevel@tonic-gate 
32890Sstevel@tonic-gate Sym *
32900Sstevel@tonic-gate kobj_lookup_kernel(const char *name)
32910Sstevel@tonic-gate {
32920Sstevel@tonic-gate 	struct modctl_list *lp;
32930Sstevel@tonic-gate 	struct module *mp;
32940Sstevel@tonic-gate 	Sym *sp;
32950Sstevel@tonic-gate 
32960Sstevel@tonic-gate 	/*
32970Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
32980Sstevel@tonic-gate 	 */
32990Sstevel@tonic-gate 	for (lp = kobj_lm_lookup(KOBJ_LM_PRIMARY); lp; lp = lp->modl_next) {
33000Sstevel@tonic-gate 		mp = mod(lp);
33010Sstevel@tonic-gate 
33020Sstevel@tonic-gate 		if (mp == NULL)
33030Sstevel@tonic-gate 			continue;
33040Sstevel@tonic-gate 
33050Sstevel@tonic-gate 		if ((sp = lookup_one(mp, name)) != NULL)
33060Sstevel@tonic-gate 			return (sp);
33070Sstevel@tonic-gate 	}
33080Sstevel@tonic-gate 	return (NULL);
33090Sstevel@tonic-gate }
33100Sstevel@tonic-gate 
33110Sstevel@tonic-gate static Sym *
33120Sstevel@tonic-gate lookup_one(struct module *mp, const char *name)
33130Sstevel@tonic-gate {
33140Sstevel@tonic-gate 	symid_t *ip;
33150Sstevel@tonic-gate 	char *name1;
33160Sstevel@tonic-gate 	Sym *sp;
33170Sstevel@tonic-gate 
33180Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
33190Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
33200Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl +
33210Sstevel@tonic-gate 		    mp->symhdr->sh_entsize * *ip);
33220Sstevel@tonic-gate 		name1 = mp->strings + sp->st_name;
33230Sstevel@tonic-gate 		if (strcmp(name, name1) == 0 &&
33240Sstevel@tonic-gate 		    ELF_ST_TYPE(sp->st_info) != STT_FILE &&
33250Sstevel@tonic-gate 		    sp->st_shndx != SHN_UNDEF &&
33260Sstevel@tonic-gate 		    sp->st_shndx != SHN_COMMON)
33270Sstevel@tonic-gate 			return (sp);
33280Sstevel@tonic-gate 	}
33290Sstevel@tonic-gate 	return (NULL);
33300Sstevel@tonic-gate }
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate /*
33330Sstevel@tonic-gate  * Lookup a given symbol pointer in the module's symbol hash.  If the symbol
33340Sstevel@tonic-gate  * is hashed, return the symbol pointer; otherwise return NULL.
33350Sstevel@tonic-gate  */
33360Sstevel@tonic-gate static Sym *
33370Sstevel@tonic-gate sym_lookup(struct module *mp, Sym *ksp)
33380Sstevel@tonic-gate {
33390Sstevel@tonic-gate 	char *name = mp->strings + ksp->st_name;
33400Sstevel@tonic-gate 	symid_t *ip;
33410Sstevel@tonic-gate 	Sym *sp;
33420Sstevel@tonic-gate 
33430Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
33440Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
33450Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + mp->symhdr->sh_entsize * *ip);
33460Sstevel@tonic-gate 		if (sp == ksp)
33470Sstevel@tonic-gate 			return (ksp);
33480Sstevel@tonic-gate 	}
33490Sstevel@tonic-gate 	return (NULL);
33500Sstevel@tonic-gate }
33510Sstevel@tonic-gate 
33520Sstevel@tonic-gate static void
33530Sstevel@tonic-gate sym_insert(struct module *mp, char *name, symid_t index)
33540Sstevel@tonic-gate {
33550Sstevel@tonic-gate 	symid_t *ip;
33560Sstevel@tonic-gate 
33570Sstevel@tonic-gate #ifdef KOBJ_DEBUG
33580Sstevel@tonic-gate 		if (kobj_debug & D_SYMBOLS) {
33590Sstevel@tonic-gate 			static struct module *lastmp = NULL;
33600Sstevel@tonic-gate 			Sym *sp;
33610Sstevel@tonic-gate 			if (lastmp != mp) {
33620Sstevel@tonic-gate 				_kobj_printf(ops,
33630Sstevel@tonic-gate 				    "krtld: symbol entry: file=%s\n",
33640Sstevel@tonic-gate 				    mp->filename);
33650Sstevel@tonic-gate 				_kobj_printf(ops,
33660Sstevel@tonic-gate 				    "krtld:\tsymndx\tvalue\t\t"
33670Sstevel@tonic-gate 				    "symbol name\n");
33680Sstevel@tonic-gate 				lastmp = mp;
33690Sstevel@tonic-gate 			}
33700Sstevel@tonic-gate 			sp = (Sym *)(mp->symtbl +
33713912Slling 			    index * mp->symhdr->sh_entsize);
33720Sstevel@tonic-gate 			_kobj_printf(ops, "krtld:\t[%3d]", index);
33730Sstevel@tonic-gate 			_kobj_printf(ops, "\t0x%lx", sp->st_value);
33740Sstevel@tonic-gate 			_kobj_printf(ops, "\t%s\n", name);
33750Sstevel@tonic-gate 		}
33760Sstevel@tonic-gate 
33770Sstevel@tonic-gate #endif
33780Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
33790Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
33800Sstevel@tonic-gate 		;
33810Sstevel@tonic-gate 	}
33820Sstevel@tonic-gate 	*ip = index;
33830Sstevel@tonic-gate }
33840Sstevel@tonic-gate 
33850Sstevel@tonic-gate struct modctl *
33860Sstevel@tonic-gate kobj_boot_mod_lookup(const char *modname)
33870Sstevel@tonic-gate {
33880Sstevel@tonic-gate 	struct modctl *mctl = kobj_modules;
33890Sstevel@tonic-gate 
33900Sstevel@tonic-gate 	do {
33910Sstevel@tonic-gate 		if (strcmp(modname, mctl->mod_modname) == 0)
33920Sstevel@tonic-gate 			return (mctl);
33930Sstevel@tonic-gate 	} while ((mctl = mctl->mod_next) != kobj_modules);
33940Sstevel@tonic-gate 
33950Sstevel@tonic-gate 	return (NULL);
33960Sstevel@tonic-gate }
33970Sstevel@tonic-gate 
33980Sstevel@tonic-gate /*
3399309Scth  * Determine if the module exists.
3400309Scth  */
3401309Scth int
3402309Scth kobj_path_exists(char *name, int use_path)
3403309Scth {
3404309Scth 	struct _buf *file;
3405309Scth 
3406309Scth 	file = kobj_open_path(name, use_path, 1);
3407309Scth #ifdef	MODDIR_SUFFIX
3408309Scth 	if (file == (struct _buf *)-1)
3409309Scth 		file = kobj_open_path(name, use_path, 0);
3410309Scth #endif	/* MODDIR_SUFFIX */
3411309Scth 	if (file == (struct _buf *)-1)
3412309Scth 		return (0);
3413309Scth 	kobj_close_file(file);
3414309Scth 	return (1);
3415309Scth }
3416309Scth 
3417309Scth /*
34180Sstevel@tonic-gate  * fullname is dynamically allocated to be able to hold the
34190Sstevel@tonic-gate  * maximum size string that can be constructed from name.
34200Sstevel@tonic-gate  * path is exactly like the shell PATH variable.
34210Sstevel@tonic-gate  */
34220Sstevel@tonic-gate struct _buf *
34230Sstevel@tonic-gate kobj_open_path(char *name, int use_path, int use_moddir_suffix)
34240Sstevel@tonic-gate {
34250Sstevel@tonic-gate 	char *p, *q;
34260Sstevel@tonic-gate 	char *pathp;
34270Sstevel@tonic-gate 	char *pathpsave;
34280Sstevel@tonic-gate 	char *fullname;
34290Sstevel@tonic-gate 	int maxpathlen;
34300Sstevel@tonic-gate 	struct _buf *file;
34310Sstevel@tonic-gate 
34320Sstevel@tonic-gate #if !defined(MODDIR_SUFFIX)
34330Sstevel@tonic-gate 	use_moddir_suffix = B_FALSE;
34340Sstevel@tonic-gate #endif
34350Sstevel@tonic-gate 
34360Sstevel@tonic-gate 	if (!use_path)
34370Sstevel@tonic-gate 		pathp = "";		/* use name as specified */
34380Sstevel@tonic-gate 	else
34393446Smrj 		pathp = kobj_module_path;
34403446Smrj 					/* use configured default path */
34410Sstevel@tonic-gate 
34420Sstevel@tonic-gate 	pathpsave = pathp;		/* keep this for error reporting */
34430Sstevel@tonic-gate 
34440Sstevel@tonic-gate 	/*
34450Sstevel@tonic-gate 	 * Allocate enough space for the largest possible fullname.
34460Sstevel@tonic-gate 	 * since path is of the form <directory> : <directory> : ...
34470Sstevel@tonic-gate 	 * we're potentially allocating a little more than we need to
34480Sstevel@tonic-gate 	 * but we'll allocate the exact amount when we find the right directory.
34490Sstevel@tonic-gate 	 * (The + 3 below is one for NULL terminator and one for the '/'
34500Sstevel@tonic-gate 	 * we might have to add at the beginning of path and one for
34510Sstevel@tonic-gate 	 * the '/' between path and name.)
34520Sstevel@tonic-gate 	 */
34530Sstevel@tonic-gate 	maxpathlen = strlen(pathp) + strlen(name) + 3;
34540Sstevel@tonic-gate 	/* sizeof includes null */
34550Sstevel@tonic-gate 	maxpathlen += sizeof (slash_moddir_suffix_slash) - 1;
34560Sstevel@tonic-gate 	fullname = kobj_zalloc(maxpathlen, KM_WAIT);
34570Sstevel@tonic-gate 
34580Sstevel@tonic-gate 	for (;;) {
34590Sstevel@tonic-gate 		p = fullname;
34600Sstevel@tonic-gate 		if (*pathp != '\0' && *pathp != '/')
34610Sstevel@tonic-gate 			*p++ = '/';	/* path must start with '/' */
34620Sstevel@tonic-gate 		while (*pathp && *pathp != ':' && *pathp != ' ')
34630Sstevel@tonic-gate 			*p++ = *pathp++;
34640Sstevel@tonic-gate 		if (p != fullname && p[-1] != '/')
34650Sstevel@tonic-gate 			*p++ = '/';
34660Sstevel@tonic-gate 		if (use_moddir_suffix) {
34670Sstevel@tonic-gate 			char *b = basename(name);
34680Sstevel@tonic-gate 			char *s;
34690Sstevel@tonic-gate 
34700Sstevel@tonic-gate 			/* copy everything up to the base name */
34710Sstevel@tonic-gate 			q = name;
34720Sstevel@tonic-gate 			while (q != b && *q)
34730Sstevel@tonic-gate 				*p++ = *q++;
34740Sstevel@tonic-gate 			s = slash_moddir_suffix_slash;
34750Sstevel@tonic-gate 			while (*s)
34760Sstevel@tonic-gate 				*p++ = *s++;
34770Sstevel@tonic-gate 			/* copy the rest */
34780Sstevel@tonic-gate 			while (*b)
34790Sstevel@tonic-gate 				*p++ = *b++;
34800Sstevel@tonic-gate 		} else {
34810Sstevel@tonic-gate 			q = name;
34820Sstevel@tonic-gate 			while (*q)
34830Sstevel@tonic-gate 				*p++ = *q++;
34840Sstevel@tonic-gate 		}
34850Sstevel@tonic-gate 		*p = 0;
34860Sstevel@tonic-gate 		if ((file = kobj_open_file(fullname)) != (struct _buf *)-1) {
34870Sstevel@tonic-gate 			kobj_free(fullname, maxpathlen);
34880Sstevel@tonic-gate 			return (file);
34890Sstevel@tonic-gate 		}
34900Sstevel@tonic-gate 		if (*pathp == 0)
34910Sstevel@tonic-gate 			break;
34920Sstevel@tonic-gate 		pathp++;
34930Sstevel@tonic-gate 	}
34940Sstevel@tonic-gate 	kobj_free(fullname, maxpathlen);
34950Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG) {
34960Sstevel@tonic-gate 		_kobj_printf(ops, "can't open %s,", name);
34970Sstevel@tonic-gate 		_kobj_printf(ops, " path is %s\n", pathpsave);
34980Sstevel@tonic-gate 	}
34990Sstevel@tonic-gate 	return ((struct _buf *)-1);
35000Sstevel@tonic-gate }
35010Sstevel@tonic-gate 
35020Sstevel@tonic-gate intptr_t
35030Sstevel@tonic-gate kobj_open(char *filename)
35040Sstevel@tonic-gate {
35050Sstevel@tonic-gate 	struct vnode *vp;
35060Sstevel@tonic-gate 	int fd;
35070Sstevel@tonic-gate 
35080Sstevel@tonic-gate 	if (_modrootloaded) {
35090Sstevel@tonic-gate 		struct kobjopen_tctl *ltp = kobjopen_alloc(filename);
35100Sstevel@tonic-gate 		int Errno;
35110Sstevel@tonic-gate 
35120Sstevel@tonic-gate 		/*
35130Sstevel@tonic-gate 		 * Hand off the open to a thread who has a
35140Sstevel@tonic-gate 		 * stack size capable handling the request.
35150Sstevel@tonic-gate 		 */
35160Sstevel@tonic-gate 		if (curthread != &t0) {
35170Sstevel@tonic-gate 			(void) thread_create(NULL, DEFAULTSTKSZ * 2,
35180Sstevel@tonic-gate 			    kobjopen_thread, ltp, 0, &p0, TS_RUN, maxclsyspri);
35190Sstevel@tonic-gate 			sema_p(&ltp->sema);
35200Sstevel@tonic-gate 			Errno = ltp->Errno;
35210Sstevel@tonic-gate 			vp = ltp->vp;
35220Sstevel@tonic-gate 		} else {
35230Sstevel@tonic-gate 			/*
35240Sstevel@tonic-gate 			 * 1098067: module creds should not be those of the
35250Sstevel@tonic-gate 			 * caller
35260Sstevel@tonic-gate 			 */
35270Sstevel@tonic-gate 			cred_t *saved_cred = curthread->t_cred;
35280Sstevel@tonic-gate 			curthread->t_cred = kcred;
35291544Seschrock 			Errno = vn_openat(filename, UIO_SYSSPACE, FREAD, 0, &vp,
35305331Samw 			    0, 0, rootdir, -1);
35310Sstevel@tonic-gate 			curthread->t_cred = saved_cred;
35320Sstevel@tonic-gate 		}
35330Sstevel@tonic-gate 		kobjopen_free(ltp);
35340Sstevel@tonic-gate 
35350Sstevel@tonic-gate 		if (Errno) {
35360Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
35370Sstevel@tonic-gate 				_kobj_printf(ops,
35380Sstevel@tonic-gate 				    "kobj_open: vn_open of %s fails, ",
35390Sstevel@tonic-gate 				    filename);
35400Sstevel@tonic-gate 				_kobj_printf(ops, "Errno = %d\n", Errno);
35410Sstevel@tonic-gate 			}
35420Sstevel@tonic-gate 			return (-1);
35430Sstevel@tonic-gate 		} else {
35440Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
35450Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_open: '%s'", filename);
35460Sstevel@tonic-gate 				_kobj_printf(ops, " vp = %p\n", vp);
35470Sstevel@tonic-gate 			}
35480Sstevel@tonic-gate 			return ((intptr_t)vp);
35490Sstevel@tonic-gate 		}
35500Sstevel@tonic-gate 	} else {
35510Sstevel@tonic-gate 		fd = kobj_boot_open(filename, 0);
35520Sstevel@tonic-gate 
35530Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG) {
35540Sstevel@tonic-gate 			if (fd < 0)
35550Sstevel@tonic-gate 				_kobj_printf(ops,
35560Sstevel@tonic-gate 				    "kobj_open: can't open %s\n", filename);
35570Sstevel@tonic-gate 			else {
35580Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_open: '%s'", filename);
35590Sstevel@tonic-gate 				_kobj_printf(ops, " descr = 0x%x\n", fd);
35600Sstevel@tonic-gate 			}
35610Sstevel@tonic-gate 		}
35620Sstevel@tonic-gate 		return ((intptr_t)fd);
35630Sstevel@tonic-gate 	}
35640Sstevel@tonic-gate }
35650Sstevel@tonic-gate 
35660Sstevel@tonic-gate /*
35670Sstevel@tonic-gate  * Calls to kobj_open() are handled off to this routine as a separate thread.
35680Sstevel@tonic-gate  */
35690Sstevel@tonic-gate static void
35700Sstevel@tonic-gate kobjopen_thread(struct kobjopen_tctl *ltp)
35710Sstevel@tonic-gate {
35720Sstevel@tonic-gate 	kmutex_t	cpr_lk;
35730Sstevel@tonic-gate 	callb_cpr_t	cpr_i;
35740Sstevel@tonic-gate 
35750Sstevel@tonic-gate 	mutex_init(&cpr_lk, NULL, MUTEX_DEFAULT, NULL);
35760Sstevel@tonic-gate 	CALLB_CPR_INIT(&cpr_i, &cpr_lk, callb_generic_cpr, "kobjopen");
35770Sstevel@tonic-gate 	ltp->Errno = vn_open(ltp->name, UIO_SYSSPACE, FREAD, 0, &(ltp->vp),
35783912Slling 	    0, 0);
35790Sstevel@tonic-gate 	sema_v(&ltp->sema);
35800Sstevel@tonic-gate 	mutex_enter(&cpr_lk);
35810Sstevel@tonic-gate 	CALLB_CPR_EXIT(&cpr_i);
35820Sstevel@tonic-gate 	mutex_destroy(&cpr_lk);
35830Sstevel@tonic-gate 	thread_exit();
35840Sstevel@tonic-gate }
35850Sstevel@tonic-gate 
35860Sstevel@tonic-gate /*
35870Sstevel@tonic-gate  * allocate and initialize a kobjopen thread structure
35880Sstevel@tonic-gate  */
35890Sstevel@tonic-gate static struct kobjopen_tctl *
35900Sstevel@tonic-gate kobjopen_alloc(char *filename)
35910Sstevel@tonic-gate {
35920Sstevel@tonic-gate 	struct kobjopen_tctl *ltp = kmem_zalloc(sizeof (*ltp), KM_SLEEP);
35930Sstevel@tonic-gate 
35940Sstevel@tonic-gate 	ASSERT(filename != NULL);
35950Sstevel@tonic-gate 
35960Sstevel@tonic-gate 	ltp->name = kmem_alloc(strlen(filename) + 1, KM_SLEEP);
35970Sstevel@tonic-gate 	bcopy(filename, ltp->name, strlen(filename) + 1);
35980Sstevel@tonic-gate 	sema_init(&ltp->sema, 0, NULL, SEMA_DEFAULT, NULL);
35990Sstevel@tonic-gate 	return (ltp);
36000Sstevel@tonic-gate }
36010Sstevel@tonic-gate 
36020Sstevel@tonic-gate /*
36030Sstevel@tonic-gate  * free a kobjopen thread control structure
36040Sstevel@tonic-gate  */
36050Sstevel@tonic-gate static void
36060Sstevel@tonic-gate kobjopen_free(struct kobjopen_tctl *ltp)
36070Sstevel@tonic-gate {
36080Sstevel@tonic-gate 	sema_destroy(&ltp->sema);
36090Sstevel@tonic-gate 	kmem_free(ltp->name, strlen(ltp->name) + 1);
36100Sstevel@tonic-gate 	kmem_free(ltp, sizeof (*ltp));
36110Sstevel@tonic-gate }
36120Sstevel@tonic-gate 
36130Sstevel@tonic-gate int
36145648Ssetje kobj_read(intptr_t descr, char *buf, uint_t size, uint_t offset)
36150Sstevel@tonic-gate {
36160Sstevel@tonic-gate 	int stat;
36170Sstevel@tonic-gate 	ssize_t resid;
36180Sstevel@tonic-gate 
36190Sstevel@tonic-gate 	if (_modrootloaded) {
36200Sstevel@tonic-gate 		if ((stat = vn_rdwr(UIO_READ, (struct vnode *)descr, buf, size,
36210Sstevel@tonic-gate 		    (offset_t)offset, UIO_SYSSPACE, 0, (rlim64_t)0, CRED(),
36220Sstevel@tonic-gate 		    &resid)) != 0) {
36230Sstevel@tonic-gate 			_kobj_printf(ops,
36240Sstevel@tonic-gate 			    "vn_rdwr failed with error 0x%x\n", stat);
36250Sstevel@tonic-gate 			return (-1);
36260Sstevel@tonic-gate 		}
36270Sstevel@tonic-gate 		return (size - resid);
36280Sstevel@tonic-gate 	} else {
36290Sstevel@tonic-gate 		int count = 0;
36300Sstevel@tonic-gate 
36310Sstevel@tonic-gate 		if (kobj_boot_seek((int)descr, (off_t)0, offset) != 0) {
36320Sstevel@tonic-gate 			_kobj_printf(ops,
36330Sstevel@tonic-gate 			    "kobj_read: seek 0x%x failed\n", offset);
36340Sstevel@tonic-gate 			return (-1);
36350Sstevel@tonic-gate 		}
36360Sstevel@tonic-gate 
36370Sstevel@tonic-gate 		count = kobj_boot_read((int)descr, buf, size);
36380Sstevel@tonic-gate 		if (count < size) {
36390Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
36400Sstevel@tonic-gate 				_kobj_printf(ops,
36410Sstevel@tonic-gate 				    "kobj_read: req %d bytes, ", size);
36420Sstevel@tonic-gate 				_kobj_printf(ops, "got %d\n", count);
36430Sstevel@tonic-gate 			}
36440Sstevel@tonic-gate 		}
36450Sstevel@tonic-gate 		return (count);
36460Sstevel@tonic-gate 	}
36470Sstevel@tonic-gate }
36480Sstevel@tonic-gate 
36490Sstevel@tonic-gate void
36500Sstevel@tonic-gate kobj_close(intptr_t descr)
36510Sstevel@tonic-gate {
36520Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG)
36530Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_close: 0x%lx\n", descr);
36540Sstevel@tonic-gate 
36550Sstevel@tonic-gate 	if (_modrootloaded) {
36560Sstevel@tonic-gate 		struct vnode *vp = (struct vnode *)descr;
36575331Samw 		(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
36580Sstevel@tonic-gate 		VN_RELE(vp);
36590Sstevel@tonic-gate 	} else
36600Sstevel@tonic-gate 		(void) kobj_boot_close((int)descr);
36610Sstevel@tonic-gate }
36620Sstevel@tonic-gate 
36631544Seschrock int
36641544Seschrock kobj_fstat(intptr_t descr, struct bootstat *buf)
36651544Seschrock {
36661544Seschrock 	if (buf == NULL)
36671544Seschrock 		return (-1);
36681544Seschrock 
36691544Seschrock 	if (_modrootloaded) {
36701544Seschrock 		vattr_t vattr;
36711544Seschrock 		struct vnode *vp = (struct vnode *)descr;
36725331Samw 		if (VOP_GETATTR(vp, &vattr, 0, kcred, NULL) != 0)
36731544Seschrock 			return (-1);
36741544Seschrock 
36751544Seschrock 		/*
36761544Seschrock 		 * The vattr and bootstat structures are similar, but not
36771544Seschrock 		 * identical.  We do our best to fill in the bootstat structure
36781544Seschrock 		 * from the contents of vattr (transfering only the ones that
36791544Seschrock 		 * are obvious.
36801544Seschrock 		 */
36811544Seschrock 
36821544Seschrock 		buf->st_mode = (uint32_t)vattr.va_mode;
36831544Seschrock 		buf->st_nlink = (uint32_t)vattr.va_nlink;
36841544Seschrock 		buf->st_uid = (int32_t)vattr.va_uid;
36851544Seschrock 		buf->st_gid = (int32_t)vattr.va_gid;
36861544Seschrock 		buf->st_rdev = (uint64_t)vattr.va_rdev;
36871544Seschrock 		buf->st_size = (uint64_t)vattr.va_size;
36881544Seschrock 		buf->st_atim.tv_sec = (int64_t)vattr.va_atime.tv_sec;
36891544Seschrock 		buf->st_atim.tv_nsec = (int64_t)vattr.va_atime.tv_nsec;
36901544Seschrock 		buf->st_mtim.tv_sec = (int64_t)vattr.va_mtime.tv_sec;
36911544Seschrock 		buf->st_mtim.tv_nsec = (int64_t)vattr.va_mtime.tv_nsec;
36921544Seschrock 		buf->st_ctim.tv_sec = (int64_t)vattr.va_ctime.tv_sec;
36931544Seschrock 		buf->st_ctim.tv_nsec = (int64_t)vattr.va_ctime.tv_nsec;
36941544Seschrock 		buf->st_blksize = (int32_t)vattr.va_blksize;
36951544Seschrock 		buf->st_blocks = (int64_t)vattr.va_nblocks;
36961544Seschrock 
36971544Seschrock 		return (0);
36981544Seschrock 	}
36991544Seschrock 
37001544Seschrock 	return (kobj_boot_fstat((int)descr, buf));
37011544Seschrock }
37021544Seschrock 
37031544Seschrock 
37040Sstevel@tonic-gate struct _buf *
37050Sstevel@tonic-gate kobj_open_file(char *name)
37060Sstevel@tonic-gate {
37070Sstevel@tonic-gate 	struct _buf *file;
37085648Ssetje 	struct compinfo cbuf;
37090Sstevel@tonic-gate 	intptr_t fd;
37100Sstevel@tonic-gate 
37110Sstevel@tonic-gate 	if ((fd = kobj_open(name)) == -1) {
37120Sstevel@tonic-gate 		return ((struct _buf *)-1);
37130Sstevel@tonic-gate 	}
37140Sstevel@tonic-gate 
37150Sstevel@tonic-gate 	file = kobj_zalloc(sizeof (struct _buf), KM_WAIT|KM_TMP);
37160Sstevel@tonic-gate 	file->_fd = fd;
37170Sstevel@tonic-gate 	file->_name = kobj_alloc(strlen(name)+1, KM_WAIT|KM_TMP);
37180Sstevel@tonic-gate 	file->_cnt = file->_size = file->_off = 0;
37190Sstevel@tonic-gate 	file->_ln = 1;
37200Sstevel@tonic-gate 	file->_ptr = file->_base;
37210Sstevel@tonic-gate 	(void) strcpy(file->_name, name);
37225648Ssetje 
37235648Ssetje 	/*
37245648Ssetje 	 * Before root is mounted, we must check
37255648Ssetje 	 * for a compressed file and do our own
37265648Ssetje 	 * buffering.
37275648Ssetje 	 */
37285648Ssetje 	if (_modrootloaded) {
37295648Ssetje 		file->_base = kobj_zalloc(MAXBSIZE, KM_WAIT);
37305648Ssetje 		file->_bsize = MAXBSIZE;
37315648Ssetje 	} else {
37325648Ssetje 		if (kobj_boot_compinfo(fd, &cbuf) != 0) {
37335648Ssetje 			kobj_close_file(file);
37345648Ssetje 			return ((struct _buf *)-1);
37355648Ssetje 		}
37365648Ssetje 		file->_iscmp = cbuf.iscmp;
37375648Ssetje 		if (file->_iscmp) {
37385648Ssetje 			if (kobj_comp_setup(file, &cbuf) != 0) {
37395648Ssetje 				kobj_close_file(file);
37405648Ssetje 				return ((struct _buf *)-1);
37415648Ssetje 			}
37425648Ssetje 		} else {
37435648Ssetje 			file->_base = kobj_zalloc(cbuf.blksize, KM_WAIT|KM_TMP);
37445648Ssetje 			file->_bsize = cbuf.blksize;
37455648Ssetje 		}
37465648Ssetje 	}
37470Sstevel@tonic-gate 	return (file);
37480Sstevel@tonic-gate }
37490Sstevel@tonic-gate 
37505648Ssetje static int
37515648Ssetje kobj_comp_setup(struct _buf *file, struct compinfo *cip)
37525648Ssetje {
37535648Ssetje 	struct comphdr *hdr;
37545648Ssetje 
37555648Ssetje 	/*
37565648Ssetje 	 * read the compressed image into memory,
37575648Ssetje 	 * so we can deompress from there
37585648Ssetje 	 */
37595648Ssetje 	file->_dsize = cip->fsize;
37605648Ssetje 	file->_dbuf = kobj_alloc(cip->fsize, KM_WAIT|KM_TMP);
37615648Ssetje 	if (kobj_read(file->_fd, file->_dbuf, cip->fsize, 0) != cip->fsize) {
37625648Ssetje 		kobj_free(file->_dbuf, cip->fsize);
37635648Ssetje 		return (-1);
37645648Ssetje 	}
37655648Ssetje 
37665648Ssetje 	hdr = kobj_comphdr(file);
37675648Ssetje 	if (hdr->ch_magic != CH_MAGIC || hdr->ch_version != CH_VERSION ||
37685648Ssetje 	    hdr->ch_algorithm != CH_ALG_ZLIB || hdr->ch_fsize == 0 ||
37695648Ssetje 	    (hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0) {
37705648Ssetje 		kobj_free(file->_dbuf, cip->fsize);
37715648Ssetje 		return (-1);
37725648Ssetje 	}
37735648Ssetje 	file->_base = kobj_alloc(hdr->ch_blksize, KM_WAIT|KM_TMP);
37745648Ssetje 	file->_bsize = hdr->ch_blksize;
37755648Ssetje 	return (0);
37765648Ssetje }
37775648Ssetje 
37780Sstevel@tonic-gate void
37790Sstevel@tonic-gate kobj_close_file(struct _buf *file)
37800Sstevel@tonic-gate {
37810Sstevel@tonic-gate 	kobj_close(file->_fd);
37825648Ssetje 	if (file->_base != NULL)
37835648Ssetje 		kobj_free(file->_base, file->_bsize);
37845648Ssetje 	if (file->_dbuf != NULL)
37855648Ssetje 		kobj_free(file->_dbuf, file->_dsize);
37860Sstevel@tonic-gate 	kobj_free(file->_name, strlen(file->_name)+1);
37870Sstevel@tonic-gate 	kobj_free(file, sizeof (struct _buf));
37880Sstevel@tonic-gate }
37890Sstevel@tonic-gate 
37900Sstevel@tonic-gate int
37915648Ssetje kobj_read_file(struct _buf *file, char *buf, uint_t size, uint_t off)
37920Sstevel@tonic-gate {
37930Sstevel@tonic-gate 	int b_size, c_size;
37940Sstevel@tonic-gate 	int b_off;	/* Offset into buffer for start of bcopy */
37950Sstevel@tonic-gate 	int count = 0;
37960Sstevel@tonic-gate 	int page_addr;
37970Sstevel@tonic-gate 
37980Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG) {
37990Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_read_file: size=%x,", size);
38000Sstevel@tonic-gate 		_kobj_printf(ops, " offset=%x at", off);
38010Sstevel@tonic-gate 		_kobj_printf(ops, " buf=%x\n", buf);
38020Sstevel@tonic-gate 	}
38030Sstevel@tonic-gate 
38040Sstevel@tonic-gate 	while (size) {
38055648Ssetje 		page_addr = F_PAGE(file, off);
38060Sstevel@tonic-gate 		b_size = file->_size;
38070Sstevel@tonic-gate 		/*
38080Sstevel@tonic-gate 		 * If we have the filesystem page the caller's referring to
38090Sstevel@tonic-gate 		 * and we have something in the buffer,
38100Sstevel@tonic-gate 		 * satisfy as much of the request from the buffer as we can.
38110Sstevel@tonic-gate 		 */
38120Sstevel@tonic-gate 		if (page_addr == file->_off && b_size > 0) {
38135648Ssetje 			b_off = B_OFFSET(file, off);
38140Sstevel@tonic-gate 			c_size = b_size - b_off;
38150Sstevel@tonic-gate 			/*
38160Sstevel@tonic-gate 			 * If there's nothing to copy, we're at EOF.
38170Sstevel@tonic-gate 			 */
38180Sstevel@tonic-gate 			if (c_size <= 0)
38190Sstevel@tonic-gate 				break;
38200Sstevel@tonic-gate 			if (c_size > size)
38210Sstevel@tonic-gate 				c_size = size;
38220Sstevel@tonic-gate 			if (buf) {
38230Sstevel@tonic-gate 				if (_moddebug & MODDEBUG_ERRMSG)
38240Sstevel@tonic-gate 					_kobj_printf(ops, "copying %x bytes\n",
38250Sstevel@tonic-gate 					    c_size);
38260Sstevel@tonic-gate 				bcopy(file->_base+b_off, buf, c_size);
38270Sstevel@tonic-gate 				size -= c_size;
38280Sstevel@tonic-gate 				off += c_size;
38290Sstevel@tonic-gate 				buf += c_size;
38300Sstevel@tonic-gate 				count += c_size;
38310Sstevel@tonic-gate 			} else {
38320Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_read: system error");
38330Sstevel@tonic-gate 				count = -1;
38340Sstevel@tonic-gate 				break;
38350Sstevel@tonic-gate 			}
38360Sstevel@tonic-gate 		} else {
38370Sstevel@tonic-gate 			/*
38380Sstevel@tonic-gate 			 * If the caller's offset is page aligned and
38390Sstevel@tonic-gate 			 * the caller want's at least a filesystem page and
38400Sstevel@tonic-gate 			 * the caller provided a buffer,
38410Sstevel@tonic-gate 			 * read directly into the caller's buffer.
38420Sstevel@tonic-gate 			 */
38430Sstevel@tonic-gate 			if (page_addr == off &&
38445648Ssetje 			    (c_size = F_BLKS(file, size)) && buf) {
38455648Ssetje 				c_size = kobj_read_blks(file, buf, c_size,
38463912Slling 				    page_addr);
38470Sstevel@tonic-gate 				if (c_size < 0) {
38480Sstevel@tonic-gate 					count = -1;
38490Sstevel@tonic-gate 					break;
38500Sstevel@tonic-gate 				}
38510Sstevel@tonic-gate 				count += c_size;
38525648Ssetje 				if (c_size != F_BLKS(file, size))
38530Sstevel@tonic-gate 					break;
38540Sstevel@tonic-gate 				size -= c_size;
38550Sstevel@tonic-gate 				off += c_size;
38560Sstevel@tonic-gate 				buf += c_size;
38570Sstevel@tonic-gate 			/*
38580Sstevel@tonic-gate 			 * Otherwise, read into our buffer and copy next time
38590Sstevel@tonic-gate 			 * around the loop.
38600Sstevel@tonic-gate 			 */
38610Sstevel@tonic-gate 			} else {
38620Sstevel@tonic-gate 				file->_off = page_addr;
38635648Ssetje 				c_size = kobj_read_blks(file, file->_base,
38645648Ssetje 				    file->_bsize, page_addr);
38650Sstevel@tonic-gate 				file->_ptr = file->_base;
38660Sstevel@tonic-gate 				file->_cnt = c_size;
38670Sstevel@tonic-gate 				file->_size = c_size;
38680Sstevel@tonic-gate 				/*
38690Sstevel@tonic-gate 				 * If a _filbuf call or nothing read, break.
38700Sstevel@tonic-gate 				 */
38710Sstevel@tonic-gate 				if (buf == NULL || c_size <= 0) {
38720Sstevel@tonic-gate 					count = c_size;
38730Sstevel@tonic-gate 					break;
38740Sstevel@tonic-gate 				}
38750Sstevel@tonic-gate 			}
38760Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG)
38770Sstevel@tonic-gate 				_kobj_printf(ops, "read %x bytes\n", c_size);
38780Sstevel@tonic-gate 		}
38790Sstevel@tonic-gate 	}
38800Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG)
38810Sstevel@tonic-gate 		_kobj_printf(ops, "count = %x\n", count);
38820Sstevel@tonic-gate 
38830Sstevel@tonic-gate 	return (count);
38840Sstevel@tonic-gate }
38850Sstevel@tonic-gate 
38865648Ssetje static int
38875648Ssetje kobj_read_blks(struct _buf *file, char *buf, uint_t size, uint_t off)
38885648Ssetje {
38895648Ssetje 	int ret;
38905648Ssetje 
38915648Ssetje 	ASSERT(B_OFFSET(file, size) == 0 && B_OFFSET(file, off) == 0);
38925648Ssetje 	if (file->_iscmp) {
38935648Ssetje 		uint_t blks;
38945648Ssetje 		int nret;
38955648Ssetje 
38965648Ssetje 		ret = 0;
38975648Ssetje 		for (blks = size / file->_bsize; blks != 0; blks--) {
38985648Ssetje 			nret = kobj_uncomp_blk(file, buf, off);
38995648Ssetje 			if (nret == -1)
39005648Ssetje 				return (-1);
39015648Ssetje 			buf += nret;
39025648Ssetje 			off += nret;
39035648Ssetje 			ret += nret;
39045648Ssetje 			if (nret < file->_bsize)
39055648Ssetje 				break;
39065648Ssetje 		}
39075648Ssetje 	} else
39085648Ssetje 		ret = kobj_read(file->_fd, buf, size, off);
39095648Ssetje 	return (ret);
39105648Ssetje }
39115648Ssetje 
39125648Ssetje static int
39135648Ssetje kobj_uncomp_blk(struct _buf *file, char *buf, uint_t off)
39145648Ssetje {
39155648Ssetje 	struct comphdr *hdr = kobj_comphdr(file);
39165648Ssetje 	ulong_t dlen, slen;
39175648Ssetje 	caddr_t src;
39185648Ssetje 	int i;
39195648Ssetje 
39205648Ssetje 	dlen = file->_bsize;
39215648Ssetje 	i = off / file->_bsize;
39225648Ssetje 	src = file->_dbuf + hdr->ch_blkmap[i];
39235648Ssetje 	if (i == hdr->ch_fsize / file->_bsize)
39246582Ssetje 		slen = file->_dsize - hdr->ch_blkmap[i];
39255648Ssetje 	else
39265648Ssetje 		slen = hdr->ch_blkmap[i + 1] - hdr->ch_blkmap[i];
39275648Ssetje 	if (z_uncompress(buf, &dlen, src, slen) != Z_OK)
39285648Ssetje 		return (-1);
39295648Ssetje 	return (dlen);
39305648Ssetje }
39315648Ssetje 
39320Sstevel@tonic-gate int
39330Sstevel@tonic-gate kobj_filbuf(struct _buf *f)
39340Sstevel@tonic-gate {
39355648Ssetje 	if (kobj_read_file(f, NULL, f->_bsize, f->_off + f->_size) > 0)
39360Sstevel@tonic-gate 		return (kobj_getc(f));
39370Sstevel@tonic-gate 	return (-1);
39380Sstevel@tonic-gate }
39390Sstevel@tonic-gate 
39400Sstevel@tonic-gate void
39410Sstevel@tonic-gate kobj_free(void *address, size_t size)
39420Sstevel@tonic-gate {
39430Sstevel@tonic-gate 	if (standalone)
39440Sstevel@tonic-gate 		return;
39450Sstevel@tonic-gate 
39460Sstevel@tonic-gate 	kmem_free(address, size);
39470Sstevel@tonic-gate 	kobj_stat.nfree_calls++;
39480Sstevel@tonic-gate 	kobj_stat.nfree += size;
39490Sstevel@tonic-gate }
39500Sstevel@tonic-gate 
39510Sstevel@tonic-gate void *
39520Sstevel@tonic-gate kobj_zalloc(size_t size, int flag)
39530Sstevel@tonic-gate {
39540Sstevel@tonic-gate 	void *v;
39550Sstevel@tonic-gate 
39560Sstevel@tonic-gate 	if ((v = kobj_alloc(size, flag)) != 0) {
39570Sstevel@tonic-gate 		bzero(v, size);
39580Sstevel@tonic-gate 	}
39590Sstevel@tonic-gate 
39600Sstevel@tonic-gate 	return (v);
39610Sstevel@tonic-gate }
39620Sstevel@tonic-gate 
39630Sstevel@tonic-gate void *
39640Sstevel@tonic-gate kobj_alloc(size_t size, int flag)
39650Sstevel@tonic-gate {
39660Sstevel@tonic-gate 	/*
39670Sstevel@tonic-gate 	 * If we are running standalone in the
39680Sstevel@tonic-gate 	 * linker, we ask boot for memory.
39690Sstevel@tonic-gate 	 * Either it's temporary memory that we lose
39700Sstevel@tonic-gate 	 * once boot is mapped out or we allocate it
39710Sstevel@tonic-gate 	 * permanently using the dynamic data segment.
39720Sstevel@tonic-gate 	 */
39730Sstevel@tonic-gate 	if (standalone) {
39745648Ssetje #if defined(_OBP)
39755648Ssetje 		if (flag & (KM_TMP | KM_SCRATCH))
39765648Ssetje 			return (bop_temp_alloc(size, MINALIGN));
39775648Ssetje #else
39780Sstevel@tonic-gate 		if (flag & (KM_TMP | KM_SCRATCH))
39790Sstevel@tonic-gate 			return (BOP_ALLOC(ops, 0, size, MINALIGN));
39800Sstevel@tonic-gate #endif
39810Sstevel@tonic-gate 		return (kobj_segbrk(&_edata, size, MINALIGN, 0));
39820Sstevel@tonic-gate 	}
39830Sstevel@tonic-gate 
39840Sstevel@tonic-gate 	kobj_stat.nalloc_calls++;
39850Sstevel@tonic-gate 	kobj_stat.nalloc += size;
39860Sstevel@tonic-gate 
39870Sstevel@tonic-gate 	return (kmem_alloc(size, (flag & KM_NOWAIT) ? KM_NOSLEEP : KM_SLEEP));
39880Sstevel@tonic-gate }
39890Sstevel@tonic-gate 
39900Sstevel@tonic-gate /*
39910Sstevel@tonic-gate  * Allow the "mod" system to sync up with the work
39920Sstevel@tonic-gate  * already done by kobj during the initial loading
39930Sstevel@tonic-gate  * of the kernel.  This also gives us a chance
39940Sstevel@tonic-gate  * to reallocate memory that belongs to boot.
39950Sstevel@tonic-gate  */
39960Sstevel@tonic-gate void
39970Sstevel@tonic-gate kobj_sync(void)
39980Sstevel@tonic-gate {
39990Sstevel@tonic-gate 	struct modctl_list *lp, **lpp;
40000Sstevel@tonic-gate 
40010Sstevel@tonic-gate 	/*
40023446Smrj 	 * The module path can be set in /etc/system via 'moddir' commands
40030Sstevel@tonic-gate 	 */
40040Sstevel@tonic-gate 	if (default_path != NULL)
40053446Smrj 		kobj_module_path = default_path;
40060Sstevel@tonic-gate 	else
40073446Smrj 		default_path = kobj_module_path;
40080Sstevel@tonic-gate 
40090Sstevel@tonic-gate 	ksyms_arena = vmem_create("ksyms", NULL, 0, sizeof (uint64_t),
40100Sstevel@tonic-gate 	    segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
40110Sstevel@tonic-gate 
40120Sstevel@tonic-gate 	ctf_arena = vmem_create("ctf", NULL, 0, sizeof (uint_t),
40130Sstevel@tonic-gate 	    segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
40140Sstevel@tonic-gate 
40150Sstevel@tonic-gate 	/*
40160Sstevel@tonic-gate 	 * Move symbol tables from boot memory to ksyms_arena.
40170Sstevel@tonic-gate 	 */
40180Sstevel@tonic-gate 	for (lpp = kobj_linkmaps; *lpp != NULL; lpp++) {
40190Sstevel@tonic-gate 		for (lp = *lpp; lp != NULL; lp = lp->modl_next)
40200Sstevel@tonic-gate 			kobj_export_module(mod(lp));
40210Sstevel@tonic-gate 	}
40220Sstevel@tonic-gate }
40230Sstevel@tonic-gate 
40240Sstevel@tonic-gate caddr_t
40250Sstevel@tonic-gate kobj_segbrk(caddr_t *spp, size_t size, size_t align, caddr_t limit)
40260Sstevel@tonic-gate {
40270Sstevel@tonic-gate 	uintptr_t va, pva;
40280Sstevel@tonic-gate 	size_t alloc_pgsz = kobj_mmu_pagesize;
40290Sstevel@tonic-gate 	size_t alloc_align = BO_NO_ALIGN;
40300Sstevel@tonic-gate 	size_t alloc_size;
40310Sstevel@tonic-gate 
40320Sstevel@tonic-gate 	/*
40330Sstevel@tonic-gate 	 * If we are using "large" mappings for the kernel,
40340Sstevel@tonic-gate 	 * request aligned memory from boot using the
40350Sstevel@tonic-gate 	 * "large" pagesize.
40360Sstevel@tonic-gate 	 */
40370Sstevel@tonic-gate 	if (lg_pagesize) {
40380Sstevel@tonic-gate 		alloc_align = lg_pagesize;
40390Sstevel@tonic-gate 		alloc_pgsz = lg_pagesize;
40400Sstevel@tonic-gate 	}
4041*6973Sjg 
4042*6973Sjg #if defined(__sparc)
4043*6973Sjg 	/* account for redzone */
4044*6973Sjg 	if (limit)
4045*6973Sjg 		limit -= alloc_pgsz;
4046*6973Sjg #endif	/* __sparc */
4047*6973Sjg 
40480Sstevel@tonic-gate 	va = ALIGN((uintptr_t)*spp, align);
40490Sstevel@tonic-gate 	pva = P2ROUNDUP((uintptr_t)*spp, alloc_pgsz);
40500Sstevel@tonic-gate 	/*
40510Sstevel@tonic-gate 	 * Need more pages?
40520Sstevel@tonic-gate 	 */
40530Sstevel@tonic-gate 	if (va + size > pva) {
40543446Smrj 		uintptr_t npva;
40553446Smrj 
40560Sstevel@tonic-gate 		alloc_size = P2ROUNDUP(size - (pva - va), alloc_pgsz);
40570Sstevel@tonic-gate 		/*
40580Sstevel@tonic-gate 		 * Check for overlapping segments.
40590Sstevel@tonic-gate 		 */
40603446Smrj 		if (limit && limit <= *spp + alloc_size) {
40610Sstevel@tonic-gate 			return ((caddr_t)0);
40623446Smrj 		}
40633446Smrj 
40643446Smrj 		npva = (uintptr_t)BOP_ALLOC(ops, (caddr_t)pva,
40653912Slling 		    alloc_size, alloc_align);
40663446Smrj 
40673446Smrj 		if (npva == NULL) {
40683446Smrj 			_kobj_printf(ops, "BOP_ALLOC failed, 0x%lx bytes",
40690Sstevel@tonic-gate 			    alloc_size);
40703446Smrj 			_kobj_printf(ops, " aligned %lx", alloc_align);
40710Sstevel@tonic-gate 			_kobj_printf(ops, " at 0x%lx\n", pva);
40723446Smrj 			return (NULL);
40730Sstevel@tonic-gate 		}
40740Sstevel@tonic-gate 	}
40750Sstevel@tonic-gate 	*spp = (caddr_t)(va + size);
40760Sstevel@tonic-gate 
40770Sstevel@tonic-gate 	return ((caddr_t)va);
40780Sstevel@tonic-gate }
40790Sstevel@tonic-gate 
40800Sstevel@tonic-gate /*
40810Sstevel@tonic-gate  * Calculate the number of output hash buckets.
40820Sstevel@tonic-gate  * We use the next prime larger than n / 4,
40830Sstevel@tonic-gate  * so the average hash chain is about 4 entries.
40840Sstevel@tonic-gate  * More buckets would just be a waste of memory.
40850Sstevel@tonic-gate  */
40860Sstevel@tonic-gate uint_t
40870Sstevel@tonic-gate kobj_gethashsize(uint_t n)
40880Sstevel@tonic-gate {
40890Sstevel@tonic-gate 	int f;
40900Sstevel@tonic-gate 	int hsize = MAX(n / 4, 2);
40910Sstevel@tonic-gate 
40920Sstevel@tonic-gate 	for (f = 2; f * f <= hsize; f++)
40930Sstevel@tonic-gate 		if (hsize % f == 0)
40940Sstevel@tonic-gate 			hsize += f = 1;
40950Sstevel@tonic-gate 
40960Sstevel@tonic-gate 	return (hsize);
40970Sstevel@tonic-gate }
40980Sstevel@tonic-gate 
40993912Slling /*
41003912Slling  * Get the file size.
41013912Slling  *
41023912Slling  * Before root is mounted, files are compressed in the boot_archive ramdisk
41033912Slling  * (in the memory). kobj_fstat would return the compressed file size.
41043912Slling  * In order to get the uncompressed file size, read the file to the end and
41053912Slling  * count its size.
41063912Slling  */
41073912Slling int
41083912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
41093912Slling {
41103912Slling 	if (_modrootloaded) {
41113912Slling 		struct bootstat bst;
41123912Slling 
41133912Slling 		if (kobj_fstat(file->_fd, &bst) != 0)
41143912Slling 			return (EIO);
41153912Slling 		*size = bst.st_size;
41163912Slling 	} else {
41175648Ssetje 
41185648Ssetje #if defined(_OBP)
41195648Ssetje 		struct bootstat bsb;
41205648Ssetje 
41215648Ssetje 		if (file->_iscmp) {
41225648Ssetje 			struct comphdr *hdr = kobj_comphdr(file);
41235648Ssetje 
41245648Ssetje 			*size = hdr->ch_fsize;
41255648Ssetje 		} else if (kobj_boot_fstat(file->_fd, &bsb) != 0)
41265648Ssetje 			return (EIO);
41275648Ssetje 		else
41285648Ssetje 			*size = bsb.st_size;
41295648Ssetje #else
41303912Slling 		char *buf;
41313912Slling 		int count;
41323912Slling 		uint64_t offset = 0;
41333912Slling 
41343912Slling 		buf = kmem_alloc(MAXBSIZE, KM_SLEEP);
41353912Slling 		do {
41363912Slling 			count = kobj_read_file(file, buf, MAXBSIZE, offset);
41373912Slling 			if (count < 0) {
41383912Slling 				kmem_free(buf, MAXBSIZE);
41393912Slling 				return (EIO);
41403912Slling 			}
41413912Slling 			offset += count;
41423912Slling 		} while (count == MAXBSIZE);
41433912Slling 		kmem_free(buf, MAXBSIZE);
41443912Slling 
41453912Slling 		*size = offset;
41465648Ssetje #endif
41473912Slling 	}
41483912Slling 
41493912Slling 	return (0);
41503912Slling }
41513912Slling 
41520Sstevel@tonic-gate static char *
41530Sstevel@tonic-gate basename(char *s)
41540Sstevel@tonic-gate {
41550Sstevel@tonic-gate 	char *p, *q;
41560Sstevel@tonic-gate 
41570Sstevel@tonic-gate 	q = NULL;
41580Sstevel@tonic-gate 	p = s;
41590Sstevel@tonic-gate 	do {
41600Sstevel@tonic-gate 		if (*p == '/')
41610Sstevel@tonic-gate 			q = p;
41620Sstevel@tonic-gate 	} while (*p++);
41630Sstevel@tonic-gate 	return (q ? q + 1 : s);
41640Sstevel@tonic-gate }
41650Sstevel@tonic-gate 
41660Sstevel@tonic-gate void
41670Sstevel@tonic-gate kobj_stat_get(kobj_stat_t *kp)
41680Sstevel@tonic-gate {
41690Sstevel@tonic-gate 	*kp = kobj_stat;
41700Sstevel@tonic-gate }
41710Sstevel@tonic-gate 
41720Sstevel@tonic-gate int
41730Sstevel@tonic-gate kobj_getpagesize()
41740Sstevel@tonic-gate {
41750Sstevel@tonic-gate 	return (lg_pagesize);
41760Sstevel@tonic-gate }
41770Sstevel@tonic-gate 
41780Sstevel@tonic-gate void
41790Sstevel@tonic-gate kobj_textwin_alloc(struct module *mp)
41800Sstevel@tonic-gate {
41810Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&mod_lock));
41820Sstevel@tonic-gate 
41830Sstevel@tonic-gate 	if (mp->textwin != NULL)
41840Sstevel@tonic-gate 		return;
41850Sstevel@tonic-gate 
41860Sstevel@tonic-gate 	/*
41870Sstevel@tonic-gate 	 * If the text is not contained in the heap, then it is not contained
41880Sstevel@tonic-gate 	 * by a writable mapping.  (Specifically, it's on the nucleus page.)
41890Sstevel@tonic-gate 	 * We allocate a read/write mapping for this module's text to allow
41900Sstevel@tonic-gate 	 * the text to be patched without calling hot_patch_kernel_text()
41910Sstevel@tonic-gate 	 * (which is quite slow).
41920Sstevel@tonic-gate 	 */
41930Sstevel@tonic-gate 	if (!vmem_contains(heaptext_arena, mp->text, mp->text_size)) {
41940Sstevel@tonic-gate 		uintptr_t text = (uintptr_t)mp->text;
41950Sstevel@tonic-gate 		uintptr_t size = (uintptr_t)mp->text_size;
41960Sstevel@tonic-gate 		uintptr_t i;
41970Sstevel@tonic-gate 		caddr_t va;
41980Sstevel@tonic-gate 		size_t sz = ((text + size + PAGESIZE - 1) & PAGEMASK) -
41990Sstevel@tonic-gate 		    (text & PAGEMASK);
42000Sstevel@tonic-gate 
42010Sstevel@tonic-gate 		va = mp->textwin_base = vmem_alloc(heap_arena, sz, VM_SLEEP);
42020Sstevel@tonic-gate 
42030Sstevel@tonic-gate 		for (i = text & PAGEMASK; i < text + size; i += PAGESIZE) {
42040Sstevel@tonic-gate 			hat_devload(kas.a_hat, va, PAGESIZE,
42050Sstevel@tonic-gate 			    hat_getpfnum(kas.a_hat, (caddr_t)i),
42060Sstevel@tonic-gate 			    PROT_READ | PROT_WRITE,
42070Sstevel@tonic-gate 			    HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
42080Sstevel@tonic-gate 			va += PAGESIZE;
42090Sstevel@tonic-gate 		}
42100Sstevel@tonic-gate 
42110Sstevel@tonic-gate 		mp->textwin = mp->textwin_base + (text & PAGEOFFSET);
42120Sstevel@tonic-gate 	} else {
42130Sstevel@tonic-gate 		mp->textwin = mp->text;
42140Sstevel@tonic-gate 	}
42150Sstevel@tonic-gate }
42160Sstevel@tonic-gate 
42170Sstevel@tonic-gate void
42180Sstevel@tonic-gate kobj_textwin_free(struct module *mp)
42190Sstevel@tonic-gate {
42200Sstevel@tonic-gate 	uintptr_t text = (uintptr_t)mp->text;
42210Sstevel@tonic-gate 	uintptr_t tsize = (uintptr_t)mp->text_size;
42220Sstevel@tonic-gate 	size_t size = (((text + tsize + PAGESIZE - 1) & PAGEMASK) -
42230Sstevel@tonic-gate 	    (text & PAGEMASK));
42240Sstevel@tonic-gate 
42250Sstevel@tonic-gate 	mp->textwin = NULL;
42260Sstevel@tonic-gate 
42270Sstevel@tonic-gate 	if (mp->textwin_base == NULL)
42280Sstevel@tonic-gate 		return;
42290Sstevel@tonic-gate 
42300Sstevel@tonic-gate 	hat_unload(kas.a_hat, mp->textwin_base, size, HAT_UNLOAD_UNLOCK);
42310Sstevel@tonic-gate 	vmem_free(heap_arena, mp->textwin_base, size);
42320Sstevel@tonic-gate 	mp->textwin_base = NULL;
42330Sstevel@tonic-gate }
42340Sstevel@tonic-gate 
42350Sstevel@tonic-gate static char *
42360Sstevel@tonic-gate find_libmacro(char *name)
42370Sstevel@tonic-gate {
42380Sstevel@tonic-gate 	int lmi;
42390Sstevel@tonic-gate 
42400Sstevel@tonic-gate 	for (lmi = 0; lmi < NLIBMACROS; lmi++) {
42410Sstevel@tonic-gate 		if (strcmp(name, libmacros[lmi].lmi_macroname) == 0)
42420Sstevel@tonic-gate 			return (libmacros[lmi].lmi_list);
42430Sstevel@tonic-gate 	}
42440Sstevel@tonic-gate 	return (NULL);
42450Sstevel@tonic-gate }
42460Sstevel@tonic-gate 
42470Sstevel@tonic-gate /*
42480Sstevel@tonic-gate  * Check for $MACRO in tail (string to expand) and expand it in path at pathend
42490Sstevel@tonic-gate  * returns path if successful, else NULL
42500Sstevel@tonic-gate  * Support multiple $MACROs expansion and the first valid path will be returned
42510Sstevel@tonic-gate  * Caller's responsibility to provide enough space in path to expand
42520Sstevel@tonic-gate  */
42530Sstevel@tonic-gate char *
42540Sstevel@tonic-gate expand_libmacro(char *tail, char *path, char *pathend)
42550Sstevel@tonic-gate {
42560Sstevel@tonic-gate 	char c, *p, *p1, *p2, *path2, *endp;
42570Sstevel@tonic-gate 	int diff, lmi, macrolen, valid_macro, more_macro;
42580Sstevel@tonic-gate 	struct _buf *file;
42590Sstevel@tonic-gate 
42600Sstevel@tonic-gate 	/*
42610Sstevel@tonic-gate 	 * check for $MACROS between nulls or slashes
42620Sstevel@tonic-gate 	 */
42630Sstevel@tonic-gate 	p = strchr(tail, '$');
42640Sstevel@tonic-gate 	if (p == NULL)
42650Sstevel@tonic-gate 		return (NULL);
42660Sstevel@tonic-gate 	for (lmi = 0; lmi < NLIBMACROS; lmi++) {
42670Sstevel@tonic-gate 		macrolen = libmacros[lmi].lmi_macrolen;
42680Sstevel@tonic-gate 		if (strncmp(p + 1, libmacros[lmi].lmi_macroname, macrolen) == 0)
42690Sstevel@tonic-gate 			break;
42700Sstevel@tonic-gate 	}
42710Sstevel@tonic-gate 
42720Sstevel@tonic-gate 	valid_macro = 0;
42730Sstevel@tonic-gate 	if (lmi < NLIBMACROS) {
42740Sstevel@tonic-gate 		/*
42750Sstevel@tonic-gate 		 * The following checks are used to restrict expansion of
42760Sstevel@tonic-gate 		 * macros to those that form a full directory/file name
42770Sstevel@tonic-gate 		 * and to keep the behavior same as before.  If this
42780Sstevel@tonic-gate 		 * restriction is removed or no longer valid in the future,
42790Sstevel@tonic-gate 		 * the checks below can be deleted.
42800Sstevel@tonic-gate 		 */
42810Sstevel@tonic-gate 		if ((p == tail) || (*(p - 1) == '/')) {
42820Sstevel@tonic-gate 			c = *(p + macrolen + 1);
42830Sstevel@tonic-gate 			if (c == '/' || c == '\0')
42840Sstevel@tonic-gate 				valid_macro = 1;
42850Sstevel@tonic-gate 		}
42860Sstevel@tonic-gate 	}
42870Sstevel@tonic-gate 
42880Sstevel@tonic-gate 	if (!valid_macro) {
42890Sstevel@tonic-gate 		p2 = strchr(p, '/');
42900Sstevel@tonic-gate 		/*
42910Sstevel@tonic-gate 		 * if no more macro to expand, then just copy whatever left
42920Sstevel@tonic-gate 		 * and check whether it exists
42930Sstevel@tonic-gate 		 */
42940Sstevel@tonic-gate 		if (p2 == NULL || strchr(p2, '$') == NULL) {
42950Sstevel@tonic-gate 			(void) strcpy(pathend, tail);
42960Sstevel@tonic-gate 			if ((file = kobj_open_path(path, 1, 1)) !=
42970Sstevel@tonic-gate 			    (struct _buf *)-1) {
42980Sstevel@tonic-gate 				kobj_close_file(file);
42990Sstevel@tonic-gate 				return (path);
43000Sstevel@tonic-gate 			} else
43010Sstevel@tonic-gate 				return (NULL);
43020Sstevel@tonic-gate 		} else {
43030Sstevel@tonic-gate 			/*
43040Sstevel@tonic-gate 			 * copy all chars before '/' and call expand_libmacro()
43050Sstevel@tonic-gate 			 * again
43060Sstevel@tonic-gate 			 */
43070Sstevel@tonic-gate 			diff = p2 - tail;
43080Sstevel@tonic-gate 			bcopy(tail, pathend, diff);
43090Sstevel@tonic-gate 			pathend += diff;
43100Sstevel@tonic-gate 			*(pathend) = '\0';
43110Sstevel@tonic-gate 			return (expand_libmacro(p2, path, pathend));
43120Sstevel@tonic-gate 		}
43130Sstevel@tonic-gate 	}
43140Sstevel@tonic-gate 
43150Sstevel@tonic-gate 	more_macro = 0;
43160Sstevel@tonic-gate 	if (c != '\0') {
43170Sstevel@tonic-gate 		endp = p + macrolen + 1;
43180Sstevel@tonic-gate 		if (strchr(endp, '$') != NULL)
43190Sstevel@tonic-gate 			more_macro = 1;
43200Sstevel@tonic-gate 	} else
43210Sstevel@tonic-gate 		endp = NULL;
43220Sstevel@tonic-gate 
43230Sstevel@tonic-gate 	/*
43240Sstevel@tonic-gate 	 * copy lmi_list and split it into components.
43250Sstevel@tonic-gate 	 * then put the part of tail before $MACRO into path
43260Sstevel@tonic-gate 	 * at pathend
43270Sstevel@tonic-gate 	 */
43280Sstevel@tonic-gate 	diff = p - tail;
43290Sstevel@tonic-gate 	if (diff > 0)
43300Sstevel@tonic-gate 		bcopy(tail, pathend, diff);
43310Sstevel@tonic-gate 	path2 = pathend + diff;
43320Sstevel@tonic-gate 	p1 = libmacros[lmi].lmi_list;
43330Sstevel@tonic-gate 	while (p1 && (*p1 != '\0')) {
43340Sstevel@tonic-gate 		p2 = strchr(p1, ':');
43350Sstevel@tonic-gate 		if (p2) {
43360Sstevel@tonic-gate 			diff = p2 - p1;
43370Sstevel@tonic-gate 			bcopy(p1, path2, diff);
43380Sstevel@tonic-gate 			*(path2 + diff) = '\0';
43390Sstevel@tonic-gate 		} else {
43400Sstevel@tonic-gate 			diff = strlen(p1);
43410Sstevel@tonic-gate 			bcopy(p1, path2, diff + 1);
43420Sstevel@tonic-gate 		}
43430Sstevel@tonic-gate 		/* copy endp only if there isn't any more macro to expand */
43440Sstevel@tonic-gate 		if (!more_macro && (endp != NULL))
43450Sstevel@tonic-gate 			(void) strcat(path2, endp);
43460Sstevel@tonic-gate 		file = kobj_open_path(path, 1, 1);
43470Sstevel@tonic-gate 		if (file != (struct _buf *)-1) {
43480Sstevel@tonic-gate 			kobj_close_file(file);
43490Sstevel@tonic-gate 			/*
43500Sstevel@tonic-gate 			 * if more macros to expand then call expand_libmacro(),
43510Sstevel@tonic-gate 			 * else return path which has the whole path
43520Sstevel@tonic-gate 			 */
43530Sstevel@tonic-gate 			if (!more_macro || (expand_libmacro(endp, path,
43540Sstevel@tonic-gate 			    path2 + diff) != NULL)) {
43550Sstevel@tonic-gate 				return (path);
43560Sstevel@tonic-gate 			}
43570Sstevel@tonic-gate 		}
43580Sstevel@tonic-gate 		if (p2)
43590Sstevel@tonic-gate 			p1 = ++p2;
43600Sstevel@tonic-gate 		else
43610Sstevel@tonic-gate 			return (NULL);
43620Sstevel@tonic-gate 	}
43630Sstevel@tonic-gate 	return (NULL);
43640Sstevel@tonic-gate }
43650Sstevel@tonic-gate 
43660Sstevel@tonic-gate static void
43670Sstevel@tonic-gate tnf_add_notifyunload(kobj_notify_f *fp)
43680Sstevel@tonic-gate {
43690Sstevel@tonic-gate 	kobj_notify_list_t *entry;
43700Sstevel@tonic-gate 
43710Sstevel@tonic-gate 	entry = kobj_alloc(sizeof (kobj_notify_list_t), KM_WAIT);
43720Sstevel@tonic-gate 	entry->kn_type = KOBJ_NOTIFY_MODUNLOADING;
43730Sstevel@tonic-gate 	entry->kn_func = fp;
43740Sstevel@tonic-gate 	(void) kobj_notify_add(entry);
43750Sstevel@tonic-gate }
43760Sstevel@tonic-gate 
43770Sstevel@tonic-gate /* ARGSUSED */
43780Sstevel@tonic-gate static void
43795648Ssetje tnf_unsplice_probes(uint_t what, struct modctl *mod)
43800Sstevel@tonic-gate {
43810Sstevel@tonic-gate 	tnf_probe_control_t **p;
43820Sstevel@tonic-gate 	tnf_tag_data_t **q;
43830Sstevel@tonic-gate 	struct module *mp = mod->mod_mp;
43840Sstevel@tonic-gate 
43850Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_TNF_PROBE))
43860Sstevel@tonic-gate 		return;
43870Sstevel@tonic-gate 
43880Sstevel@tonic-gate 	for (p = &__tnf_probe_list_head; *p; )
43890Sstevel@tonic-gate 		if (kobj_addrcheck(mp, (char *)*p) == 0)
43900Sstevel@tonic-gate 			*p = (*p)->next;
43910Sstevel@tonic-gate 		else
43920Sstevel@tonic-gate 			p = &(*p)->next;
43930Sstevel@tonic-gate 
43940Sstevel@tonic-gate 	for (q = &__tnf_tag_list_head; *q; )
43950Sstevel@tonic-gate 		if (kobj_addrcheck(mp, (char *)*q) == 0)
43960Sstevel@tonic-gate 			*q = (tnf_tag_data_t *)(*q)->tag_version;
43970Sstevel@tonic-gate 		else
43980Sstevel@tonic-gate 			q = (tnf_tag_data_t **)&(*q)->tag_version;
43990Sstevel@tonic-gate 
44000Sstevel@tonic-gate 	tnf_changed_probe_list = 1;
44010Sstevel@tonic-gate }
44020Sstevel@tonic-gate 
44030Sstevel@tonic-gate int
44040Sstevel@tonic-gate tnf_splice_probes(int boot_load, tnf_probe_control_t *plist,
44050Sstevel@tonic-gate     tnf_tag_data_t *tlist)
44060Sstevel@tonic-gate {
44070Sstevel@tonic-gate 	int result = 0;
44080Sstevel@tonic-gate 	static int add_notify = 1;
44090Sstevel@tonic-gate 
44100Sstevel@tonic-gate 	if (plist) {
44110Sstevel@tonic-gate 		tnf_probe_control_t *pl;
44120Sstevel@tonic-gate 
44130Sstevel@tonic-gate 		for (pl = plist; pl->next; )
44140Sstevel@tonic-gate 			pl = pl->next;
44150Sstevel@tonic-gate 
44160Sstevel@tonic-gate 		if (!boot_load)
44170Sstevel@tonic-gate 			mutex_enter(&mod_lock);
44180Sstevel@tonic-gate 		tnf_changed_probe_list = 1;
44190Sstevel@tonic-gate 		pl->next = __tnf_probe_list_head;
44200Sstevel@tonic-gate 		__tnf_probe_list_head = plist;
44210Sstevel@tonic-gate 		if (!boot_load)
44220Sstevel@tonic-gate 			mutex_exit(&mod_lock);
44230Sstevel@tonic-gate 		result = 1;
44240Sstevel@tonic-gate 	}
44250Sstevel@tonic-gate 
44260Sstevel@tonic-gate 	if (tlist) {
44270Sstevel@tonic-gate 		tnf_tag_data_t *tl;
44280Sstevel@tonic-gate 
44290Sstevel@tonic-gate 		for (tl = tlist; tl->tag_version; )
44300Sstevel@tonic-gate 			tl = (tnf_tag_data_t *)tl->tag_version;
44310Sstevel@tonic-gate 
44320Sstevel@tonic-gate 		if (!boot_load)
44330Sstevel@tonic-gate 			mutex_enter(&mod_lock);
44340Sstevel@tonic-gate 		tl->tag_version = (tnf_tag_version_t *)__tnf_tag_list_head;
44350Sstevel@tonic-gate 		__tnf_tag_list_head = tlist;
44360Sstevel@tonic-gate 		if (!boot_load)
44370Sstevel@tonic-gate 			mutex_exit(&mod_lock);
44380Sstevel@tonic-gate 		result = 1;
44390Sstevel@tonic-gate 	}
44400Sstevel@tonic-gate 	if (!boot_load && result && add_notify) {
44410Sstevel@tonic-gate 		tnf_add_notifyunload(tnf_unsplice_probes);
44420Sstevel@tonic-gate 		add_notify = 0;
44430Sstevel@tonic-gate 	}
44440Sstevel@tonic-gate 	return (result);
44450Sstevel@tonic-gate }
44460Sstevel@tonic-gate 
44475648Ssetje char *kobj_file_buf;
44485648Ssetje int kobj_file_bufsize;
44495648Ssetje 
44500Sstevel@tonic-gate /*
44510Sstevel@tonic-gate  * This code is for the purpose of manually recording which files
44520Sstevel@tonic-gate  * needs to go into the boot archive on any given system.
44530Sstevel@tonic-gate  *
44540Sstevel@tonic-gate  * To enable the code, set kobj_file_bufsize in /etc/system
44550Sstevel@tonic-gate  * and reboot the system, then use mdb to look at kobj_file_buf.
44560Sstevel@tonic-gate  */
44570Sstevel@tonic-gate static void
44580Sstevel@tonic-gate kobj_record_file(char *filename)
44590Sstevel@tonic-gate {
44600Sstevel@tonic-gate 	static char *buf;
44610Sstevel@tonic-gate 	static int size = 0;
44620Sstevel@tonic-gate 	int n;
44630Sstevel@tonic-gate 
44640Sstevel@tonic-gate 	if (kobj_file_bufsize == 0)	/* don't bother */
44650Sstevel@tonic-gate 		return;
44660Sstevel@tonic-gate 
44670Sstevel@tonic-gate 	if (kobj_file_buf == NULL) {	/* allocate buffer */
44680Sstevel@tonic-gate 		size = kobj_file_bufsize;
44690Sstevel@tonic-gate 		buf = kobj_file_buf = kobj_alloc(size, KM_WAIT|KM_TMP);
44700Sstevel@tonic-gate 	}
44710Sstevel@tonic-gate 
44720Sstevel@tonic-gate 	n = snprintf(buf, size, "%s\n", filename);
44730Sstevel@tonic-gate 	if (n > size)
44740Sstevel@tonic-gate 		n = size;
44750Sstevel@tonic-gate 	size -= n;
44760Sstevel@tonic-gate 	buf += n;
44770Sstevel@tonic-gate }
44780Sstevel@tonic-gate 
44791544Seschrock static int
44801544Seschrock kobj_boot_fstat(int fd, struct bootstat *stp)
44811544Seschrock {
44825648Ssetje #if defined(_OBP)
44831544Seschrock 	if (!standalone && _ioquiesced)
44841544Seschrock 		return (-1);
44851544Seschrock 	return (BOP_FSTAT(ops, fd, stp));
44861544Seschrock #else
44871544Seschrock 	return (BRD_FSTAT(bfs_ops, fd, stp));
44881544Seschrock #endif
44891544Seschrock }
44901544Seschrock 
44910Sstevel@tonic-gate static int
44920Sstevel@tonic-gate kobj_boot_open(char *filename, int flags)
44930Sstevel@tonic-gate {
44945648Ssetje #if defined(_OBP)
44955648Ssetje 
44960Sstevel@tonic-gate 	/*
44970Sstevel@tonic-gate 	 * If io via bootops is quiesced, it means boot is no longer
44980Sstevel@tonic-gate 	 * available to us.  We make it look as if we can't open the
44990Sstevel@tonic-gate 	 * named file - which is reasonably accurate.
45000Sstevel@tonic-gate 	 */
45010Sstevel@tonic-gate 	if (!standalone && _ioquiesced)
45020Sstevel@tonic-gate 		return (-1);
45030Sstevel@tonic-gate 
45045648Ssetje 	kobj_record_file(filename);
45055648Ssetje 	return (BOP_OPEN(filename, flags));
45060Sstevel@tonic-gate #else /* x86 */
45070Sstevel@tonic-gate 	kobj_record_file(filename);
45080Sstevel@tonic-gate 	return (BRD_OPEN(bfs_ops, filename, flags));
45090Sstevel@tonic-gate #endif
45100Sstevel@tonic-gate }
45110Sstevel@tonic-gate 
45120Sstevel@tonic-gate static int
45130Sstevel@tonic-gate kobj_boot_close(int fd)
45140Sstevel@tonic-gate {
45155648Ssetje #if defined(_OBP)
45160Sstevel@tonic-gate 	if (!standalone && _ioquiesced)
45170Sstevel@tonic-gate 		return (-1);
45180Sstevel@tonic-gate 
45195648Ssetje 	return (BOP_CLOSE(fd));
45200Sstevel@tonic-gate #else /* x86 */
45210Sstevel@tonic-gate 	return (BRD_CLOSE(bfs_ops, fd));
45220Sstevel@tonic-gate #endif
45230Sstevel@tonic-gate }
45240Sstevel@tonic-gate 
45250Sstevel@tonic-gate /*ARGSUSED*/
45260Sstevel@tonic-gate static int
45270Sstevel@tonic-gate kobj_boot_seek(int fd, off_t hi, off_t lo)
45280Sstevel@tonic-gate {
45295648Ssetje #if defined(_OBP)
45305648Ssetje 	return (BOP_SEEK(fd, lo) == -1 ? -1 : 0);
45310Sstevel@tonic-gate #else
45320Sstevel@tonic-gate 	return (BRD_SEEK(bfs_ops, fd, lo, SEEK_SET));
45330Sstevel@tonic-gate #endif
45340Sstevel@tonic-gate }
45350Sstevel@tonic-gate 
45360Sstevel@tonic-gate static int
45370Sstevel@tonic-gate kobj_boot_read(int fd, caddr_t buf, size_t size)
45380Sstevel@tonic-gate {
45395648Ssetje #if defined(_OBP)
45405648Ssetje 	return (BOP_READ(fd, buf, size));
45410Sstevel@tonic-gate #else
45420Sstevel@tonic-gate 	return (BRD_READ(bfs_ops, fd, buf, size));
45430Sstevel@tonic-gate #endif
45440Sstevel@tonic-gate }
45455648Ssetje 
45465648Ssetje static int
45475648Ssetje kobj_boot_compinfo(int fd, struct compinfo *cb)
45485648Ssetje {
45495648Ssetje 	return (boot_compinfo(fd, cb));
45505648Ssetje }
4551