xref: /onnv-gate/usr/src/uts/common/krtld/kobj.c (revision 309:ce16da2e9351)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Kernel's linker/loader
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <sys/types.h>
340Sstevel@tonic-gate #include <sys/param.h>
350Sstevel@tonic-gate #include <sys/sysmacros.h>
360Sstevel@tonic-gate #include <sys/systm.h>
370Sstevel@tonic-gate #include <sys/user.h>
380Sstevel@tonic-gate #include <sys/kmem.h>
390Sstevel@tonic-gate #include <sys/reboot.h>
400Sstevel@tonic-gate #include <sys/bootconf.h>
410Sstevel@tonic-gate #include <sys/debug.h>
420Sstevel@tonic-gate #include <sys/uio.h>
430Sstevel@tonic-gate #include <sys/file.h>
440Sstevel@tonic-gate #include <sys/vnode.h>
450Sstevel@tonic-gate #include <sys/user.h>
460Sstevel@tonic-gate #include <sys/mman.h>
470Sstevel@tonic-gate #include <vm/as.h>
480Sstevel@tonic-gate #include <vm/seg_kp.h>
490Sstevel@tonic-gate #include <vm/seg_kmem.h>
500Sstevel@tonic-gate #include <sys/elf.h>
510Sstevel@tonic-gate #include <sys/elf_notes.h>
520Sstevel@tonic-gate #include <sys/vmsystm.h>
530Sstevel@tonic-gate #include <sys/kdi.h>
540Sstevel@tonic-gate #include <sys/atomic.h>
550Sstevel@tonic-gate #include <sys/kmdb.h>
560Sstevel@tonic-gate 
570Sstevel@tonic-gate #include <sys/link.h>
580Sstevel@tonic-gate #include <sys/kobj.h>
590Sstevel@tonic-gate #include <sys/ksyms.h>
600Sstevel@tonic-gate #include <sys/disp.h>
610Sstevel@tonic-gate #include <sys/modctl.h>
620Sstevel@tonic-gate #include <sys/varargs.h>
630Sstevel@tonic-gate #include <sys/kstat.h>
640Sstevel@tonic-gate #include <sys/kobj_impl.h>
650Sstevel@tonic-gate #include <sys/callb.h>
660Sstevel@tonic-gate #include <sys/cmn_err.h>
670Sstevel@tonic-gate #include <sys/tnf_probe.h>
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #include <reloc.h>
700Sstevel@tonic-gate #include <kobj_kdi.h>
710Sstevel@tonic-gate #include <sys/sha1.h>
720Sstevel@tonic-gate #include <sys/crypto/elfsign.h>
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #if !defined(__sparc)
750Sstevel@tonic-gate #include <sys/bootvfs.h>
760Sstevel@tonic-gate #endif
770Sstevel@tonic-gate 
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate  * do_symbols() error codes
800Sstevel@tonic-gate  */
810Sstevel@tonic-gate #define	DOSYM_UNDEF		-1	/* undefined symbol */
820Sstevel@tonic-gate #define	DOSYM_UNSAFE		-2	/* MT-unsafe driver symbol */
830Sstevel@tonic-gate 
840Sstevel@tonic-gate static struct module *load_exec(val_t *);
850Sstevel@tonic-gate static void load_linker(val_t *);
860Sstevel@tonic-gate static struct modctl *add_primary(char *filename, int);
870Sstevel@tonic-gate static int bind_primary(val_t *, int);
880Sstevel@tonic-gate static int load_primary(struct module *, int);
890Sstevel@tonic-gate static int load_kmdb(val_t *);
900Sstevel@tonic-gate static int get_progbits(struct module *, struct _buf *);
910Sstevel@tonic-gate static int get_syms(struct module *, struct _buf *);
920Sstevel@tonic-gate static int get_ctf(struct module *, struct _buf *);
930Sstevel@tonic-gate static void get_signature(struct module *, struct _buf *);
940Sstevel@tonic-gate static int do_common(struct module *);
950Sstevel@tonic-gate static void add_dependent(struct module *, struct module *);
960Sstevel@tonic-gate static int do_dependents(struct modctl *, char *, size_t);
970Sstevel@tonic-gate static int do_symbols(struct module *, Elf64_Addr);
980Sstevel@tonic-gate static void module_assign(struct modctl *, struct module *);
990Sstevel@tonic-gate static void free_module_data(struct module *);
1000Sstevel@tonic-gate static char *depends_on(struct module *);
1010Sstevel@tonic-gate static char *getmodpath(void);
1020Sstevel@tonic-gate static char *basename(char *);
1030Sstevel@tonic-gate static void attr_val(val_t *);
1040Sstevel@tonic-gate static char *find_libmacro(char *);
1050Sstevel@tonic-gate static char *expand_libmacro(char *, char *, char *);
1060Sstevel@tonic-gate static int read_bootflags(void);
1070Sstevel@tonic-gate static int kobj_boot_open(char *, int);
1080Sstevel@tonic-gate static int kobj_boot_close(int);
1090Sstevel@tonic-gate static int kobj_boot_seek(int, off_t, off_t);
1100Sstevel@tonic-gate static int kobj_boot_read(int, caddr_t, size_t);
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static Sym *lookup_one(struct module *, const char *);
1130Sstevel@tonic-gate static void sym_insert(struct module *, char *, symid_t);
1140Sstevel@tonic-gate static Sym *sym_lookup(struct module *, Sym *);
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*PRINTFLIKE2*/
1170Sstevel@tonic-gate static void kprintf(void *, const char *, ...)  __KPRINTFLIKE(2);
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate static struct kobjopen_tctl *kobjopen_alloc(char *filename);
1200Sstevel@tonic-gate static void kobjopen_free(struct kobjopen_tctl *ltp);
1210Sstevel@tonic-gate static void kobjopen_thread(struct kobjopen_tctl *ltp);
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate extern int kcopy(const void *, void *, size_t);
1240Sstevel@tonic-gate extern int elf_mach_ok(Ehdr *);
1250Sstevel@tonic-gate extern int alloc_gottable(struct module *, caddr_t *, caddr_t *);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate static void tnf_unsplice_probes(unsigned int, struct modctl *);
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate extern int modrootloaded;
1300Sstevel@tonic-gate extern int swaploaded;
1310Sstevel@tonic-gate extern int bop_io_quiesced;
1320Sstevel@tonic-gate extern int last_module_id;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate #ifdef KOBJ_DEBUG
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate  * Values that can be or'd in to kobj_debug and their effects:
1370Sstevel@tonic-gate  *
1380Sstevel@tonic-gate  *	D_DEBUG		- misc. debugging information.
1390Sstevel@tonic-gate  *	D_SYMBOLS	- list symbols and their values as they are entered
1400Sstevel@tonic-gate  *			  into the hash table
1410Sstevel@tonic-gate  *	D_RELOCATIONS	- display relocation processing information
1420Sstevel@tonic-gate  *	D_LOADING	- display information about each module as it
1430Sstevel@tonic-gate  *			  is loaded.
1440Sstevel@tonic-gate  */
1450Sstevel@tonic-gate int kobj_debug = 0;
1460Sstevel@tonic-gate #endif
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate #define	MODPATH_PROPNAME	"module-path"
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
1510Sstevel@tonic-gate static char slash_moddir_suffix_slash[] = MODDIR_SUFFIX "/";
1520Sstevel@tonic-gate #else
1530Sstevel@tonic-gate #define	slash_moddir_suffix_slash	""
1540Sstevel@tonic-gate #endif
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate #define	_moddebug	get_weakish_int(&moddebug)
1570Sstevel@tonic-gate #define	_modrootloaded	get_weakish_int(&modrootloaded)
1580Sstevel@tonic-gate #define	_swaploaded	get_weakish_int(&swaploaded)
1590Sstevel@tonic-gate #define	_ioquiesced	get_weakish_int(&bop_io_quiesced)
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate #define	mod(X)		(struct module *)((X)->modl_modp->mod_mp)
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate void	*romp;		/* rom vector (opaque to us) */
1640Sstevel@tonic-gate struct bootops *ops;	/* bootops vector */
1650Sstevel@tonic-gate void *dbvec;		/* debug vector */
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate  * kobjopen thread control structure
1690Sstevel@tonic-gate  */
1700Sstevel@tonic-gate struct kobjopen_tctl {
1710Sstevel@tonic-gate 	ksema_t		sema;
1720Sstevel@tonic-gate 	char		*name;		/* name of file */
1730Sstevel@tonic-gate 	struct vnode	*vp;		/* vnode return from vn_open() */
1740Sstevel@tonic-gate 	int		Errno;		/* error return from vnopen    */
1750Sstevel@tonic-gate };
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate /*
1780Sstevel@tonic-gate  * Structure for defining dynamically expandable library macros
1790Sstevel@tonic-gate  */
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate struct lib_macro_info {
1820Sstevel@tonic-gate 	char	*lmi_list;		/* ptr to list of possible choices */
1830Sstevel@tonic-gate 	char	*lmi_macroname;		/* pointer to macro name */
1840Sstevel@tonic-gate 	ushort_t lmi_ba_index;		/* index into bootaux vector */
1850Sstevel@tonic-gate 	ushort_t lmi_macrolen;		/* macro length */
1860Sstevel@tonic-gate } libmacros[] = {
1870Sstevel@tonic-gate 	{ NULL, "CPU", BA_CPU, 0 },
1880Sstevel@tonic-gate 	{ NULL, "MMU", BA_MMU, 0 }
1890Sstevel@tonic-gate };
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate #define	NLIBMACROS	sizeof (libmacros) / sizeof (struct lib_macro_info)
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate char *boot_cpu_compatible_list;			/* make $CPU available */
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate #ifdef	MPSAS
1960Sstevel@tonic-gate void	sas_prisyms(struct modctl_list *);
1970Sstevel@tonic-gate void	sas_syms(struct module *);
1980Sstevel@tonic-gate #endif
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate vmem_t	*text_arena;				/* module text arena */
2010Sstevel@tonic-gate static vmem_t *data_arena;			/* module data & bss arena */
2020Sstevel@tonic-gate static vmem_t *ctf_arena;			/* CTF debug data arena */
2030Sstevel@tonic-gate static struct modctl *kobj_modules = NULL;	/* modules loaded */
2040Sstevel@tonic-gate static char *module_path;			/* module search path */
2050Sstevel@tonic-gate int kobj_mmu_pagesize;				/* system pagesize */
2060Sstevel@tonic-gate static int lg_pagesize;				/* "large" pagesize */
2070Sstevel@tonic-gate static int kobj_last_module_id = 0;		/* id assignment */
2080Sstevel@tonic-gate static kmutex_t kobj_lock;			/* protects mach memory list */
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate  * The following functions have been implemented by the kernel.
2120Sstevel@tonic-gate  * However, many 3rd party drivers provide their own implementations
2130Sstevel@tonic-gate  * of these functions.  When such drivers are loaded, messages
2140Sstevel@tonic-gate  * indicateing that these symbols have been mulply defined will be
2150Sstevel@tonic-gate  * emitted to the console.  To avoid alarming customers for no good
2160Sstevel@tonic-gate  * reason, we simply suppress such warnings for the following set of
2170Sstevel@tonic-gate  * functions.
2180Sstevel@tonic-gate  */
2190Sstevel@tonic-gate static char *suppress_sym_list[] =
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	"strstr",
2220Sstevel@tonic-gate 	"strncat",
2230Sstevel@tonic-gate 	"strlcat",
2240Sstevel@tonic-gate 	"strlcpy",
2250Sstevel@tonic-gate 	"strspn",
2260Sstevel@tonic-gate 	"memcpy",
2270Sstevel@tonic-gate 	"memset",
2280Sstevel@tonic-gate 	"memmove",
2290Sstevel@tonic-gate 	"memcmp",
2300Sstevel@tonic-gate 	"memchr",
2310Sstevel@tonic-gate 	"__udivdi3",
2320Sstevel@tonic-gate 	"__divdi3",
2330Sstevel@tonic-gate 	"__umoddi3",
2340Sstevel@tonic-gate 	"__moddi3",
2350Sstevel@tonic-gate 	NULL		/* This entry must exist */
2360Sstevel@tonic-gate };
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate /* indexed by KOBJ_NOTIFY_* */
2390Sstevel@tonic-gate static kobj_notify_list_t *kobj_notifiers[KOBJ_NOTIFY_MAX + 1];
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate /*
2420Sstevel@tonic-gate  * TNF probe management globals
2430Sstevel@tonic-gate  */
2440Sstevel@tonic-gate tnf_probe_control_t	*__tnf_probe_list_head = NULL;
2450Sstevel@tonic-gate tnf_tag_data_t		*__tnf_tag_list_head = NULL;
2460Sstevel@tonic-gate int			tnf_changed_probe_list = 0;
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate  * Prefix for statically defined tracing (SDT) DTrace probes.
2500Sstevel@tonic-gate  */
2510Sstevel@tonic-gate const char		*sdt_prefix = "__dtrace_probe_";
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate #if defined(__sparc)
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate  * Some PROMs return SUNW,UltraSPARC when they actually have
2560Sstevel@tonic-gate  * SUNW,UltraSPARC-II cpus. SInce we're now filtering out all
2570Sstevel@tonic-gate  * SUNW,UltraSPARC systems during the boot phase, we can safely
2580Sstevel@tonic-gate  * point the auxv CPU value at SUNW,UltraSPARC-II. This is what
2590Sstevel@tonic-gate  * we point it at.
2600Sstevel@tonic-gate  */
2610Sstevel@tonic-gate const char		*ultra_2 = "SUNW,UltraSPARC-II";
2620Sstevel@tonic-gate #endif
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate /*
2650Sstevel@tonic-gate  * Beginning and end of the kernel's
2660Sstevel@tonic-gate  * dynamic text/data segments.
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate static caddr_t _text;
2690Sstevel@tonic-gate static caddr_t _etext;
2700Sstevel@tonic-gate static caddr_t	_data;
2710Sstevel@tonic-gate caddr_t _edata;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate static Addr dynseg = 0;	/* load address of "dynamic" segment */
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate int standalone = 1;			/* an unwholey kernel? */
2760Sstevel@tonic-gate int use_iflush;				/* iflush after relocations */
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate  * _kobj_printf()
2800Sstevel@tonic-gate  *
2810Sstevel@tonic-gate  * Common printf function pointer. Can handle only one conversion
2820Sstevel@tonic-gate  * specification in the format string. Some of the functions invoked
2830Sstevel@tonic-gate  * through this function pointer cannot handle more that one conversion
2840Sstevel@tonic-gate  * specification in the format string.
2850Sstevel@tonic-gate  */
2860Sstevel@tonic-gate void (*_kobj_printf)(void *, const char *, ...);	/* printf routine */
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate static kobj_stat_t kobj_stat;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate #define	MINALIGN	8	/* at least a double-word */
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate int
2930Sstevel@tonic-gate get_weakish_int(int *ip)
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate 	if (standalone)
2960Sstevel@tonic-gate 		return (0);
2970Sstevel@tonic-gate 	return (ip == NULL ? 0 : *ip);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate static void *
3010Sstevel@tonic-gate get_weakish_pointer(void **ptrp)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	if (standalone)
3040Sstevel@tonic-gate 		return (0);
3050Sstevel@tonic-gate 	return (ptrp == NULL ? 0 : *ptrp);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate /*
3090Sstevel@tonic-gate  * XXX fix dependencies on "kernel"; this should work
3100Sstevel@tonic-gate  * for other standalone binaries as well.
3110Sstevel@tonic-gate  *
3120Sstevel@tonic-gate  * XXX Fix hashing code to use one pointer to
3130Sstevel@tonic-gate  * hash entries.
3140Sstevel@tonic-gate  *	|----------|
3150Sstevel@tonic-gate  *	| nbuckets |
3160Sstevel@tonic-gate  *	|----------|
3170Sstevel@tonic-gate  *	| nchains  |
3180Sstevel@tonic-gate  *	|----------|
3190Sstevel@tonic-gate  *	| bucket[] |
3200Sstevel@tonic-gate  *	|----------|
3210Sstevel@tonic-gate  *	| chain[]  |
3220Sstevel@tonic-gate  *	|----------|
3230Sstevel@tonic-gate  */
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate  * Load, bind and relocate all modules that
3270Sstevel@tonic-gate  * form the primary kernel. At this point, our
3280Sstevel@tonic-gate  * externals have not been relocated.
3290Sstevel@tonic-gate  */
3300Sstevel@tonic-gate void
3310Sstevel@tonic-gate kobj_init(
3320Sstevel@tonic-gate 	void *romvec,
3330Sstevel@tonic-gate 	void *dvec,
3340Sstevel@tonic-gate 	struct bootops *bootvec,
3350Sstevel@tonic-gate 	val_t *bootaux)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 	struct module *mp;
3380Sstevel@tonic-gate 	struct modctl *modp;
3390Sstevel@tonic-gate 	Addr entry;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	/*
3420Sstevel@tonic-gate 	 * Save these to pass on to
3430Sstevel@tonic-gate 	 * the booted standalone.
3440Sstevel@tonic-gate 	 */
3450Sstevel@tonic-gate 	romp = romvec;
3460Sstevel@tonic-gate 	dbvec = dvec;
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	ops = bootvec;
3490Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
3500Sstevel@tonic-gate 	_kobj_printf = (void (*)(void *, const char *, ...))ops->bsys_printf;
3510Sstevel@tonic-gate #else
3520Sstevel@tonic-gate 	_kobj_printf = (void (*)(void *, const char *, ...))bop_putsarg;
3530Sstevel@tonic-gate #endif
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate #if defined(__sparc)
3560Sstevel@tonic-gate 	/* XXXQ should suppress this test on sun4v */
3570Sstevel@tonic-gate 	if (bootaux[BA_CPU].ba_ptr) {
3580Sstevel@tonic-gate 		if (strcmp("SUNW,UltraSPARC", bootaux[BA_CPU].ba_ptr) == 0) {
3590Sstevel@tonic-gate 			bootaux[BA_CPU].ba_ptr = (void *) ultra_2;
3600Sstevel@tonic-gate 		}
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate #endif
3630Sstevel@tonic-gate 	/*
3640Sstevel@tonic-gate 	 * Save the interesting attribute-values
3650Sstevel@tonic-gate 	 * (scanned by kobj_boot).
3660Sstevel@tonic-gate 	 */
3670Sstevel@tonic-gate 	attr_val(bootaux);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	/*
3700Sstevel@tonic-gate 	 * Check bootops version.
3710Sstevel@tonic-gate 	 */
3720Sstevel@tonic-gate 	if (BOP_GETVERSION(ops) != BO_VERSION) {
3730Sstevel@tonic-gate 		_kobj_printf(ops, "Warning: Using boot version %d, ",
3740Sstevel@tonic-gate 		    BOP_GETVERSION(ops));
3750Sstevel@tonic-gate 		_kobj_printf(ops, "expected %d\n", BO_VERSION);
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/*
3790Sstevel@tonic-gate 	 * We don't support standalone debuggers anymore.  The use of kadb
3800Sstevel@tonic-gate 	 * will interfere with the later use of kmdb.  Let the user mend
3810Sstevel@tonic-gate 	 * their ways now.  Users will reach this message if they still
3820Sstevel@tonic-gate 	 * have the kadb binary on their system (perhaps they used an old
3830Sstevel@tonic-gate 	 * bfu, or maybe they intentionally copied it there) and have
3840Sstevel@tonic-gate 	 * specified its use in a way that eluded our checking in the boot
3850Sstevel@tonic-gate 	 * program.
3860Sstevel@tonic-gate 	 */
3870Sstevel@tonic-gate 	if (dvec != NULL) {
3880Sstevel@tonic-gate 		_kobj_printf(ops, "\nWARNING: Standalone debuggers such as "
3890Sstevel@tonic-gate 		    "kadb are no longer supported\n\n");
3900Sstevel@tonic-gate 		goto fail;
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate #ifndef __sparc
3940Sstevel@tonic-gate 	{
3950Sstevel@tonic-gate 		/* on x86, we always boot with a ramdisk */
3960Sstevel@tonic-gate 		extern int kobj_boot_mountroot(void);
3970Sstevel@tonic-gate 		(void) kobj_boot_mountroot();
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate #endif
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	/*
4020Sstevel@tonic-gate 	 * Set the module search path.
4030Sstevel@tonic-gate 	 */
4040Sstevel@tonic-gate 	module_path = getmodpath();
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	boot_cpu_compatible_list = find_libmacro("CPU");
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	/*
4090Sstevel@tonic-gate 	 * These two modules have actually been
4100Sstevel@tonic-gate 	 * loaded by boot, but we finish the job
4110Sstevel@tonic-gate 	 * by introducing them into the world of
4120Sstevel@tonic-gate 	 * loadable modules.
4130Sstevel@tonic-gate 	 */
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	mp = load_exec(bootaux);
4160Sstevel@tonic-gate 	load_linker(bootaux);
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	/*
4190Sstevel@tonic-gate 	 * Load all the primary dependent modules.
4200Sstevel@tonic-gate 	 */
4210Sstevel@tonic-gate 	if (load_primary(mp, KOBJ_LM_PRIMARY) == -1)
4220Sstevel@tonic-gate 		goto fail;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	/*
4250Sstevel@tonic-gate 	 * Glue it together.
4260Sstevel@tonic-gate 	 */
4270Sstevel@tonic-gate 	if (bind_primary(bootaux, KOBJ_LM_PRIMARY) == -1)
4280Sstevel@tonic-gate 		goto fail;
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	entry = bootaux[BA_ENTRY].ba_val;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate #ifdef	__sparc
4330Sstevel@tonic-gate 	/*
4340Sstevel@tonic-gate 	 * On sparcv9, boot scratch memory is running out.
4350Sstevel@tonic-gate 	 * Free the temporary allocations here to allow boot
4360Sstevel@tonic-gate 	 * to continue.
4370Sstevel@tonic-gate 	 */
4380Sstevel@tonic-gate 	kobj_tmp_free();
4390Sstevel@tonic-gate #endif
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	/*
4420Sstevel@tonic-gate 	 * Get the boot flags
4430Sstevel@tonic-gate 	 */
4440Sstevel@tonic-gate 	bootflags(ops);
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	if (boothowto & RB_VERBOSE)
4470Sstevel@tonic-gate 		kobj_lm_dump(KOBJ_LM_PRIMARY);
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	kobj_kdi_init();
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	if (boothowto & RB_KMDB) {
4520Sstevel@tonic-gate 		if (load_kmdb(bootaux) < 0)
4530Sstevel@tonic-gate 			goto fail;
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	/*
4570Sstevel@tonic-gate 	 * Post setup.
4580Sstevel@tonic-gate 	 */
4590Sstevel@tonic-gate #ifdef	MPSAS
4600Sstevel@tonic-gate 	sas_prisyms(kobj_lm_lookup(KOBJ_LM_PRIMARY));
4610Sstevel@tonic-gate #endif
4620Sstevel@tonic-gate 	s_text = _text;
4630Sstevel@tonic-gate 	e_text = _etext;
4640Sstevel@tonic-gate 	s_data = _data;
4650Sstevel@tonic-gate 	e_data = _edata;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	kobj_sync_instruction_memory(s_text, e_text - s_text);
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
4700Sstevel@tonic-gate 	if (kobj_debug & D_DEBUG)
4710Sstevel@tonic-gate 		_kobj_printf(ops,
4720Sstevel@tonic-gate 		    "krtld: transferring control to: 0x%p\n", entry);
4730Sstevel@tonic-gate #endif
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	/*
4760Sstevel@tonic-gate 	 * Make sure the mod system knows about the modules already loaded.
4770Sstevel@tonic-gate 	 */
4780Sstevel@tonic-gate 	last_module_id = kobj_last_module_id;
4790Sstevel@tonic-gate 	bcopy(kobj_modules, &modules, sizeof (modules));
4800Sstevel@tonic-gate 	modp = &modules;
4810Sstevel@tonic-gate 	do {
4820Sstevel@tonic-gate 		if (modp->mod_next == kobj_modules)
4830Sstevel@tonic-gate 			modp->mod_next = &modules;
4840Sstevel@tonic-gate 		if (modp->mod_prev == kobj_modules)
4850Sstevel@tonic-gate 			modp->mod_prev = &modules;
4860Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	standalone = 0;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate #ifdef	__sparc
4910Sstevel@tonic-gate 	/*
4920Sstevel@tonic-gate 	 * On sparcv9, boot scratch memory is running out.
4930Sstevel@tonic-gate 	 * Free the temporary allocations here to allow boot
4940Sstevel@tonic-gate 	 * to continue.
4950Sstevel@tonic-gate 	 */
4960Sstevel@tonic-gate 	kobj_tmp_free();
4970Sstevel@tonic-gate #endif
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	_kobj_printf = kprintf;
5000Sstevel@tonic-gate 	exitto((caddr_t)entry);
5010Sstevel@tonic-gate fail:
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	_kobj_printf(ops, "krtld: error during initial load/link phase\n");
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate /*
5070Sstevel@tonic-gate  * Set up any global information derived
5080Sstevel@tonic-gate  * from attribute/values in the boot or
5090Sstevel@tonic-gate  * aux vector.
5100Sstevel@tonic-gate  */
5110Sstevel@tonic-gate static void
5120Sstevel@tonic-gate attr_val(val_t *bootaux)
5130Sstevel@tonic-gate {
5140Sstevel@tonic-gate 	Phdr *phdr;
5150Sstevel@tonic-gate 	int phnum, phsize;
5160Sstevel@tonic-gate 	int i;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	kobj_mmu_pagesize = bootaux[BA_PAGESZ].ba_val;
5190Sstevel@tonic-gate 	lg_pagesize = bootaux[BA_LPAGESZ].ba_val;
5200Sstevel@tonic-gate 	use_iflush = bootaux[BA_IFLUSH].ba_val;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	phdr = (Phdr *)bootaux[BA_PHDR].ba_ptr;
5230Sstevel@tonic-gate 	phnum = bootaux[BA_PHNUM].ba_val;
5240Sstevel@tonic-gate 	phsize = bootaux[BA_PHENT].ba_val;
5250Sstevel@tonic-gate 	for (i = 0; i < phnum; i++) {
5260Sstevel@tonic-gate 		phdr = (Phdr *)(bootaux[BA_PHDR].ba_val + i * phsize);
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		if (phdr->p_type != PT_LOAD)
5290Sstevel@tonic-gate 			continue;
5300Sstevel@tonic-gate 		/*
5310Sstevel@tonic-gate 		 * Bounds of the various segments.
5320Sstevel@tonic-gate 		 */
5330Sstevel@tonic-gate 		if (!(phdr->p_flags & PF_X)) {
5340Sstevel@tonic-gate 			dynseg = phdr->p_vaddr;
5350Sstevel@tonic-gate 		} else {
5360Sstevel@tonic-gate 			if (phdr->p_flags & PF_W) {
5370Sstevel@tonic-gate 					_data = (caddr_t)phdr->p_vaddr;
5380Sstevel@tonic-gate 					_edata = _data + phdr->p_memsz;
5390Sstevel@tonic-gate 			} else {
5400Sstevel@tonic-gate 				_text = (caddr_t)phdr->p_vaddr;
5410Sstevel@tonic-gate 				_etext = _text + phdr->p_memsz;
5420Sstevel@tonic-gate 			}
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	/* To do the kobj_alloc, _edata needs to be set. */
5470Sstevel@tonic-gate 	for (i = 0; i < NLIBMACROS; i++) {
5480Sstevel@tonic-gate 		if (bootaux[libmacros[i].lmi_ba_index].ba_ptr != NULL) {
5490Sstevel@tonic-gate 			libmacros[i].lmi_list = kobj_alloc(
5500Sstevel@tonic-gate 			    strlen(bootaux[libmacros[i].lmi_ba_index].ba_ptr) +
5510Sstevel@tonic-gate 			    1, KM_WAIT);
5520Sstevel@tonic-gate 			(void) strcpy(libmacros[i].lmi_list,
5530Sstevel@tonic-gate 				bootaux[libmacros[i].lmi_ba_index].ba_ptr);
5540Sstevel@tonic-gate 		}
5550Sstevel@tonic-gate 		libmacros[i].lmi_macrolen = strlen(libmacros[i].lmi_macroname);
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate  * Set up the booted executable.
5610Sstevel@tonic-gate  */
5620Sstevel@tonic-gate static struct module *
5630Sstevel@tonic-gate load_exec(val_t *bootaux)
5640Sstevel@tonic-gate {
5650Sstevel@tonic-gate 	char filename[MAXPATHLEN];
5660Sstevel@tonic-gate 	struct modctl *cp;
5670Sstevel@tonic-gate 	struct module *mp;
5680Sstevel@tonic-gate 	Dyn *dyn;
5690Sstevel@tonic-gate 	Sym *sp;
5700Sstevel@tonic-gate 	int i, lsize, osize, nsize, allocsize;
5710Sstevel@tonic-gate 	char *libname, *tmp;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	(void) BOP_GETPROP(ops, "whoami", filename);
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	cp = add_primary(filename, KOBJ_LM_PRIMARY);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
5780Sstevel@tonic-gate 	cp->mod_mp = mp;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	/*
5810Sstevel@tonic-gate 	 * We don't have the following information
5820Sstevel@tonic-gate 	 * since this module is an executable and not
5830Sstevel@tonic-gate 	 * a relocatable .o.
5840Sstevel@tonic-gate 	 */
5850Sstevel@tonic-gate 	mp->symtbl_section = 0;
5860Sstevel@tonic-gate 	mp->shdrs = NULL;
5870Sstevel@tonic-gate 	mp->strhdr = NULL;
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	/*
5900Sstevel@tonic-gate 	 * Since this module is the only exception,
5910Sstevel@tonic-gate 	 * we cons up some section headers.
5920Sstevel@tonic-gate 	 */
5930Sstevel@tonic-gate 	mp->symhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT);
5940Sstevel@tonic-gate 	mp->strhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT);
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	mp->symhdr->sh_type = SHT_SYMTAB;
5970Sstevel@tonic-gate 	mp->strhdr->sh_type = SHT_STRTAB;
5980Sstevel@tonic-gate 	/*
5990Sstevel@tonic-gate 	 * Scan the dynamic structure.
6000Sstevel@tonic-gate 	 */
6010Sstevel@tonic-gate 	for (dyn = (Dyn *) bootaux[BA_DYNAMIC].ba_ptr;
6020Sstevel@tonic-gate 	    dyn->d_tag != DT_NULL; dyn++) {
6030Sstevel@tonic-gate 		switch (dyn->d_tag) {
6040Sstevel@tonic-gate 		case DT_SYMTAB:
6050Sstevel@tonic-gate 			dyn->d_un.d_ptr += dynseg;
6060Sstevel@tonic-gate 			mp->symspace = mp->symtbl = (char *)dyn->d_un.d_ptr;
6070Sstevel@tonic-gate 			mp->symhdr->sh_addr = dyn->d_un.d_ptr;
6080Sstevel@tonic-gate 			break;
6090Sstevel@tonic-gate 		case DT_HASH:
6100Sstevel@tonic-gate 			dyn->d_un.d_ptr += dynseg;
6110Sstevel@tonic-gate 			mp->nsyms = *((uint_t *)dyn->d_un.d_ptr + 1);
6120Sstevel@tonic-gate 			mp->hashsize = *(uint_t *)dyn->d_un.d_ptr;
6130Sstevel@tonic-gate 			break;
6140Sstevel@tonic-gate 		case DT_STRTAB:
6150Sstevel@tonic-gate 			dyn->d_un.d_ptr += dynseg;
6160Sstevel@tonic-gate 			mp->strings = (char *)dyn->d_un.d_ptr;
6170Sstevel@tonic-gate 			mp->strhdr->sh_addr = dyn->d_un.d_ptr;
6180Sstevel@tonic-gate 			break;
6190Sstevel@tonic-gate 		case DT_STRSZ:
6200Sstevel@tonic-gate 			mp->strhdr->sh_size = dyn->d_un.d_val;
6210Sstevel@tonic-gate 			break;
6220Sstevel@tonic-gate 		case DT_SYMENT:
6230Sstevel@tonic-gate 			mp->symhdr->sh_entsize = dyn->d_un.d_val;
6240Sstevel@tonic-gate 			break;
6250Sstevel@tonic-gate 		}
6260Sstevel@tonic-gate 	}
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/*
6290Sstevel@tonic-gate 	 * Collapse any DT_NEEDED entries into one string.
6300Sstevel@tonic-gate 	 */
6310Sstevel@tonic-gate 	nsize = osize = 0;
6320Sstevel@tonic-gate 	allocsize = MAXPATHLEN;
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	mp->depends_on = kobj_alloc(allocsize, KM_WAIT);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	for (dyn = (Dyn *) bootaux[BA_DYNAMIC].ba_ptr;
6370Sstevel@tonic-gate 	    dyn->d_tag != DT_NULL; dyn++)
6380Sstevel@tonic-gate 		if (dyn->d_tag == DT_NEEDED) {
6390Sstevel@tonic-gate 			char *_lib;
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 			libname = mp->strings + dyn->d_un.d_val;
6420Sstevel@tonic-gate 			if (strchr(libname, '$') != NULL) {
6430Sstevel@tonic-gate 				if ((_lib = expand_libmacro(libname,
6440Sstevel@tonic-gate 				    filename, filename)) != NULL)
6450Sstevel@tonic-gate 					libname = _lib;
6460Sstevel@tonic-gate 				else
6470Sstevel@tonic-gate 					_kobj_printf(ops, "krtld: "
6480Sstevel@tonic-gate 					    "load_exec: fail to "
6490Sstevel@tonic-gate 					    "expand %s\n", libname);
6500Sstevel@tonic-gate 			}
6510Sstevel@tonic-gate 			lsize = strlen(libname);
6520Sstevel@tonic-gate 			nsize += lsize;
6530Sstevel@tonic-gate 			if (nsize + 1 > allocsize) {
6540Sstevel@tonic-gate 				tmp = kobj_alloc(allocsize + MAXPATHLEN,
6550Sstevel@tonic-gate 				    KM_WAIT);
6560Sstevel@tonic-gate 				bcopy(mp->depends_on, tmp, osize);
6570Sstevel@tonic-gate 				kobj_free(mp->depends_on, allocsize);
6580Sstevel@tonic-gate 				mp->depends_on = tmp;
6590Sstevel@tonic-gate 				allocsize += MAXPATHLEN;
6600Sstevel@tonic-gate 			}
6610Sstevel@tonic-gate 			bcopy(libname, mp->depends_on + osize, lsize);
6620Sstevel@tonic-gate 			*(mp->depends_on + nsize) = ' '; /* seperate */
6630Sstevel@tonic-gate 			nsize++;
6640Sstevel@tonic-gate 			osize = nsize;
6650Sstevel@tonic-gate 		}
6660Sstevel@tonic-gate 	if (nsize) {
6670Sstevel@tonic-gate 		mp->depends_on[nsize - 1] = '\0'; /* terminate the string */
6680Sstevel@tonic-gate 		/*
6690Sstevel@tonic-gate 		 * alloc with exact size and copy whatever it got over
6700Sstevel@tonic-gate 		 */
6710Sstevel@tonic-gate 		tmp = kobj_alloc(nsize, KM_WAIT);
6720Sstevel@tonic-gate 		bcopy(mp->depends_on, tmp, nsize);
6730Sstevel@tonic-gate 		kobj_free(mp->depends_on, allocsize);
6740Sstevel@tonic-gate 		mp->depends_on = tmp;
6750Sstevel@tonic-gate 	} else {
6760Sstevel@tonic-gate 		kobj_free(mp->depends_on, allocsize);
6770Sstevel@tonic-gate 		mp->depends_on = NULL;
6780Sstevel@tonic-gate 	}
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	mp->flags = KOBJ_EXEC|KOBJ_PRIM;	/* NOT a relocatable .o */
6810Sstevel@tonic-gate 	mp->symhdr->sh_size = mp->nsyms * mp->symhdr->sh_entsize;
6820Sstevel@tonic-gate 	/*
6830Sstevel@tonic-gate 	 * We allocate our own table since we don't
6840Sstevel@tonic-gate 	 * hash undefined references.
6850Sstevel@tonic-gate 	 */
6860Sstevel@tonic-gate 	mp->chains = kobj_zalloc(mp->nsyms * sizeof (symid_t), KM_WAIT);
6870Sstevel@tonic-gate 	mp->buckets = kobj_zalloc(mp->hashsize * sizeof (symid_t), KM_WAIT);
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	mp->text = _text;
6900Sstevel@tonic-gate 	mp->data = _data;
6910Sstevel@tonic-gate 	cp->mod_text = mp->text;
6920Sstevel@tonic-gate 	cp->mod_text_size = mp->text_size;
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	mp->filename = cp->mod_filename;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
6970Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
6980Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
6990Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext: 0x%p", mp->text);
7000Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
7010Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata: 0x%p", mp->data);
7020Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
7030Sstevel@tonic-gate 	}
7040Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	/*
7070Sstevel@tonic-gate 	 * Insert symbols into the hash table.
7080Sstevel@tonic-gate 	 */
7090Sstevel@tonic-gate 	for (i = 0; i < mp->nsyms; i++) {
7100Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
7130Sstevel@tonic-gate 			continue;
7140Sstevel@tonic-gate #ifdef	__sparc
7150Sstevel@tonic-gate 		/*
7160Sstevel@tonic-gate 		 * Register symbols are ignored in the kernel
7170Sstevel@tonic-gate 		 */
7180Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_SPARC_REGISTER)
7190Sstevel@tonic-gate 			continue;
7200Sstevel@tonic-gate #endif	/* __sparc */
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 		sym_insert(mp, mp->strings + sp->st_name, i);
7230Sstevel@tonic-gate 	}
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	return (mp);
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate /*
7290Sstevel@tonic-gate  * Set up the linker module.
7300Sstevel@tonic-gate  */
7310Sstevel@tonic-gate static void
7320Sstevel@tonic-gate load_linker(val_t *bootaux)
7330Sstevel@tonic-gate {
7340Sstevel@tonic-gate 	struct module *kmp = (struct module *)kobj_modules->mod_mp;
7350Sstevel@tonic-gate 	struct module *mp;
7360Sstevel@tonic-gate 	struct modctl *cp;
7370Sstevel@tonic-gate 	int i;
7380Sstevel@tonic-gate 	Shdr *shp;
7390Sstevel@tonic-gate 	Sym *sp;
7400Sstevel@tonic-gate 	int shsize;
7410Sstevel@tonic-gate 	char *dlname = (char *)bootaux[BA_LDNAME].ba_ptr;
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	cp = add_primary(dlname, KOBJ_LM_PRIMARY);
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	cp->mod_mp = mp;
7480Sstevel@tonic-gate 	mp->hdr = *(Ehdr *)bootaux[BA_LDELF].ba_ptr;
7490Sstevel@tonic-gate 	shsize = mp->hdr.e_shentsize * mp->hdr.e_shnum;
7500Sstevel@tonic-gate 	mp->shdrs = kobj_alloc(shsize, KM_WAIT);
7510Sstevel@tonic-gate 	bcopy(bootaux[BA_LDSHDR].ba_ptr, mp->shdrs, shsize);
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 	for (i = 1; i < (int)mp->hdr.e_shnum; i++) {
7540Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + (i * mp->hdr.e_shentsize));
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 		if (shp->sh_flags & SHF_ALLOC) {
7570Sstevel@tonic-gate 			if (shp->sh_flags & SHF_WRITE) {
7580Sstevel@tonic-gate 				if (mp->data == NULL)
7590Sstevel@tonic-gate 					mp->data = (char *)shp->sh_addr;
7600Sstevel@tonic-gate 			} else if (mp->text == NULL) {
7610Sstevel@tonic-gate 				mp->text = (char *)shp->sh_addr;
7620Sstevel@tonic-gate 			}
7630Sstevel@tonic-gate 		}
7640Sstevel@tonic-gate 		if (shp->sh_type == SHT_SYMTAB) {
7650Sstevel@tonic-gate 			mp->symtbl_section = i;
7660Sstevel@tonic-gate 			mp->symhdr = shp;
7670Sstevel@tonic-gate 			mp->symspace = mp->symtbl = (char *)shp->sh_addr;
7680Sstevel@tonic-gate 		}
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 	mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize;
7710Sstevel@tonic-gate 	mp->flags = KOBJ_INTERP|KOBJ_PRIM;
7720Sstevel@tonic-gate 	mp->strhdr = (Shdr *)
7730Sstevel@tonic-gate 		(mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize);
7740Sstevel@tonic-gate 	mp->strings = (char *)mp->strhdr->sh_addr;
7750Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	mp->symsize = mp->symhdr->sh_size + mp->strhdr->sh_size + sizeof (int) +
7780Sstevel@tonic-gate 		(mp->hashsize + mp->nsyms) * sizeof (symid_t);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	mp->chains = kobj_zalloc(mp->nsyms * sizeof (symid_t), KM_WAIT);
7810Sstevel@tonic-gate 	mp->buckets = kobj_zalloc(mp->hashsize * sizeof (symid_t), KM_WAIT);
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	mp->bss = bootaux[BA_BSS].ba_val;
7840Sstevel@tonic-gate 	mp->bss_align = 0;	/* pre-aligned during allocation */
7850Sstevel@tonic-gate 	mp->bss_size = (uintptr_t)_edata - mp->bss;
7860Sstevel@tonic-gate 	mp->text_size = _etext - mp->text;
7870Sstevel@tonic-gate 	mp->data_size = _edata - mp->data;
7880Sstevel@tonic-gate 	mp->filename = cp->mod_filename;
7890Sstevel@tonic-gate 	cp->mod_text = mp->text;
7900Sstevel@tonic-gate 	cp->mod_text_size = mp->text_size;
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	/*
7930Sstevel@tonic-gate 	 * Now that we've figured out where the linker is,
7940Sstevel@tonic-gate 	 * set the limits for the booted object.
7950Sstevel@tonic-gate 	 */
7960Sstevel@tonic-gate 	kmp->text_size = (size_t)(mp->text - kmp->text);
7970Sstevel@tonic-gate 	kmp->data_size = (size_t)(mp->data - kmp->data);
7980Sstevel@tonic-gate 	kobj_modules->mod_text_size = kmp->text_size;
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
8010Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
8020Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
8030Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext:0x%p", mp->text);
8040Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
8050Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata:0x%p", mp->data);
8060Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
8070Sstevel@tonic-gate 	}
8080Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	/*
8110Sstevel@tonic-gate 	 * Insert the symbols into the hash table.
8120Sstevel@tonic-gate 	 */
8130Sstevel@tonic-gate 	for (i = 0; i < mp->nsyms; i++) {
8140Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
8170Sstevel@tonic-gate 			continue;
8180Sstevel@tonic-gate 		if (ELF_ST_BIND(sp->st_info) == STB_GLOBAL) {
8190Sstevel@tonic-gate 			if (sp->st_shndx == SHN_COMMON)
8200Sstevel@tonic-gate 				sp->st_shndx = SHN_ABS;
8210Sstevel@tonic-gate 		}
8220Sstevel@tonic-gate 		sym_insert(mp, mp->strings + sp->st_name, i);
8230Sstevel@tonic-gate 	}
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate static kobj_notify_list_t **
8280Sstevel@tonic-gate kobj_notify_lookup(uint_t type)
8290Sstevel@tonic-gate {
8300Sstevel@tonic-gate 	ASSERT(type != 0 && type < sizeof (kobj_notifiers) /
8310Sstevel@tonic-gate 	    sizeof (kobj_notify_list_t *));
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	return (&kobj_notifiers[type]);
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate int
8370Sstevel@tonic-gate kobj_notify_add(kobj_notify_list_t *knp)
8380Sstevel@tonic-gate {
8390Sstevel@tonic-gate 	kobj_notify_list_t **knl;
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	knl = kobj_notify_lookup(knp->kn_type);
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	knp->kn_next = NULL;
8440Sstevel@tonic-gate 	knp->kn_prev = NULL;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 	if (*knl != NULL) {
8490Sstevel@tonic-gate 		(*knl)->kn_prev = knp;
8500Sstevel@tonic-gate 		knp->kn_next = *knl;
8510Sstevel@tonic-gate 	}
8520Sstevel@tonic-gate 	(*knl) = knp;
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
8550Sstevel@tonic-gate 	return (0);
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate int
8590Sstevel@tonic-gate kobj_notify_remove(kobj_notify_list_t *knp)
8600Sstevel@tonic-gate {
8610Sstevel@tonic-gate 	kobj_notify_list_t **knl = kobj_notify_lookup(knp->kn_type);
8620Sstevel@tonic-gate 	kobj_notify_list_t *tknp;
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 	/* LINTED */
8670Sstevel@tonic-gate 	if (tknp = knp->kn_next)
8680Sstevel@tonic-gate 		tknp->kn_prev = knp->kn_prev;
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	/* LINTED */
8710Sstevel@tonic-gate 	if (tknp = knp->kn_prev)
8720Sstevel@tonic-gate 		tknp->kn_next = knp->kn_next;
8730Sstevel@tonic-gate 	else
8740Sstevel@tonic-gate 		*knl = knp->kn_next;
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	return (0);
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate /*
8820Sstevel@tonic-gate  * Notify all interested callbacks of a specified change in module state.
8830Sstevel@tonic-gate  */
8840Sstevel@tonic-gate static void
8850Sstevel@tonic-gate kobj_notify(int type, struct modctl *modp)
8860Sstevel@tonic-gate {
8870Sstevel@tonic-gate 	kobj_notify_list_t *knp;
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	if (modp->mod_loadflags & MOD_NONOTIFY || standalone)
8900Sstevel@tonic-gate 		return;
8910Sstevel@tonic-gate 
8920Sstevel@tonic-gate 	mutex_enter(&kobj_lock);
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	for (knp = *(kobj_notify_lookup(type)); knp != NULL; knp = knp->kn_next)
8950Sstevel@tonic-gate 		knp->kn_func(type, modp);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	/*
8980Sstevel@tonic-gate 	 * KDI notification must be last (it has to allow for work done by the
8990Sstevel@tonic-gate 	 * other notification callbacks), so we call it manually.
9000Sstevel@tonic-gate 	 */
9010Sstevel@tonic-gate 	kobj_kdi_mod_notify(type, modp);
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 	mutex_exit(&kobj_lock);
9040Sstevel@tonic-gate }
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate /*
9070Sstevel@tonic-gate  * Ask boot for the module path.
9080Sstevel@tonic-gate  */
9090Sstevel@tonic-gate static char *
9100Sstevel@tonic-gate getmodpath(void)
9110Sstevel@tonic-gate {
9120Sstevel@tonic-gate 	char *path;
9130Sstevel@tonic-gate 	int len;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 	if ((len = BOP_GETPROPLEN(ops, MODPATH_PROPNAME)) == -1)
9160Sstevel@tonic-gate 		return (MOD_DEFPATH);
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	path = kobj_zalloc(len, KM_WAIT);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	(void) BOP_GETPROP(ops, MODPATH_PROPNAME, path);
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	return (*path ? path : MOD_DEFPATH);
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate static struct modctl *
9260Sstevel@tonic-gate add_primary(char *filename, int lmid)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate 	struct modctl *cp;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	cp = kobj_zalloc(sizeof (struct modctl), KM_WAIT);
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate 	cp->mod_filename = kobj_alloc(strlen(filename) + 1, KM_WAIT);
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate 	/*
9350Sstevel@tonic-gate 	 * For symbol lookup, we assemble our own
9360Sstevel@tonic-gate 	 * modctl list of the primary modules.
9370Sstevel@tonic-gate 	 */
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	(void) strcpy(cp->mod_filename, filename);
9400Sstevel@tonic-gate 	cp->mod_modname = basename(cp->mod_filename);
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	/* set values for modinfo assuming that the load will work */
9430Sstevel@tonic-gate 	cp->mod_prim = 1;
9440Sstevel@tonic-gate 	cp->mod_loaded = 1;
9450Sstevel@tonic-gate 	cp->mod_installed = 1;
9460Sstevel@tonic-gate 	cp->mod_loadcnt = 1;
9470Sstevel@tonic-gate 	cp->mod_loadflags = MOD_NOAUTOUNLOAD;
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	cp->mod_id = kobj_last_module_id++;
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	/*
9520Sstevel@tonic-gate 	 * Link the module in. We'll pass this info on
9530Sstevel@tonic-gate 	 * to the mod squad later.
9540Sstevel@tonic-gate 	 */
9550Sstevel@tonic-gate 	if (kobj_modules == NULL) {
9560Sstevel@tonic-gate 		kobj_modules = cp;
9570Sstevel@tonic-gate 		cp->mod_prev = cp->mod_next = cp;
9580Sstevel@tonic-gate 	} else {
9590Sstevel@tonic-gate 		cp->mod_prev = kobj_modules->mod_prev;
9600Sstevel@tonic-gate 		cp->mod_next = kobj_modules;
9610Sstevel@tonic-gate 		kobj_modules->mod_prev->mod_next = cp;
9620Sstevel@tonic-gate 		kobj_modules->mod_prev = cp;
9630Sstevel@tonic-gate 	}
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	kobj_lm_append(lmid, cp);
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	return (cp);
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate static int
9710Sstevel@tonic-gate bind_primary(val_t *bootaux, int lmid)
9720Sstevel@tonic-gate {
9730Sstevel@tonic-gate 	struct modctl_list *linkmap = kobj_lm_lookup(lmid);
9740Sstevel@tonic-gate 	struct modctl_list *lp;
9750Sstevel@tonic-gate 	struct module *mp;
9760Sstevel@tonic-gate 	Dyn *dyn;
9770Sstevel@tonic-gate 	Word relasz;
9780Sstevel@tonic-gate 	Word relaent;
9790Sstevel@tonic-gate 	char *rela;
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	/*
9820Sstevel@tonic-gate 	 * Do common symbols.
9830Sstevel@tonic-gate 	 */
9840Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
9850Sstevel@tonic-gate 		mp = mod(lp);
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 		/*
9880Sstevel@tonic-gate 		 * Don't do common section relocations for modules that
9890Sstevel@tonic-gate 		 * don't need it.
9900Sstevel@tonic-gate 		 */
9910Sstevel@tonic-gate 		if (mp->flags & (KOBJ_EXEC|KOBJ_INTERP))
9920Sstevel@tonic-gate 			continue;
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 		if (do_common(mp) < 0)
9950Sstevel@tonic-gate 			return (-1);
9960Sstevel@tonic-gate 	}
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 	/*
9990Sstevel@tonic-gate 	 * Resolve symbols.
10000Sstevel@tonic-gate 	 */
10010Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
10020Sstevel@tonic-gate 		mp = mod(lp);
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 		if (do_symbols(mp, 0) < 0)
10050Sstevel@tonic-gate 			return (-1);
10060Sstevel@tonic-gate 	}
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 	/*
10090Sstevel@tonic-gate 	 * Do relocations.
10100Sstevel@tonic-gate 	 */
10110Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
10120Sstevel@tonic-gate 		mp = mod(lp);
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC) {
10150Sstevel@tonic-gate 			Word	shtype;
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 			relasz = 0;
10180Sstevel@tonic-gate 			relaent = 0;
10190Sstevel@tonic-gate 			rela = NULL;
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 			for (dyn = (Dyn *)bootaux[BA_DYNAMIC].ba_ptr;
10220Sstevel@tonic-gate 			    dyn->d_tag != DT_NULL; dyn++) {
10230Sstevel@tonic-gate 				switch (dyn->d_tag) {
10240Sstevel@tonic-gate 				case DT_RELASZ:
10250Sstevel@tonic-gate 				case DT_RELSZ:
10260Sstevel@tonic-gate 					relasz = dyn->d_un.d_val;
10270Sstevel@tonic-gate 					break;
10280Sstevel@tonic-gate 				case DT_RELAENT:
10290Sstevel@tonic-gate 				case DT_RELENT:
10300Sstevel@tonic-gate 					relaent = dyn->d_un.d_val;
10310Sstevel@tonic-gate 					break;
10320Sstevel@tonic-gate 				case DT_RELA:
10330Sstevel@tonic-gate 					shtype = SHT_RELA;
10340Sstevel@tonic-gate 					rela = (char *)(dyn->d_un.d_ptr +
10350Sstevel@tonic-gate 						dynseg);
10360Sstevel@tonic-gate 					break;
10370Sstevel@tonic-gate 				case DT_REL:
10380Sstevel@tonic-gate 					shtype = SHT_REL;
10390Sstevel@tonic-gate 					rela = (char *)(dyn->d_un.d_ptr +
10400Sstevel@tonic-gate 						dynseg);
10410Sstevel@tonic-gate 					break;
10420Sstevel@tonic-gate 				}
10430Sstevel@tonic-gate 			}
10440Sstevel@tonic-gate 			if (relasz == 0 ||
10450Sstevel@tonic-gate 			    relaent == 0 || rela == NULL) {
10460Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: bind_primary(): "
10470Sstevel@tonic-gate 				    "no relocation information found for "
10480Sstevel@tonic-gate 				    "module %s\n", mp->filename);
10490Sstevel@tonic-gate 				return (-1);
10500Sstevel@tonic-gate 			}
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
10530Sstevel@tonic-gate 			if (kobj_debug & D_RELOCATIONS)
10540Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: relocating: file=%s "
10550Sstevel@tonic-gate 				    "KOBJ_EXEC\n", mp->filename);
10560Sstevel@tonic-gate #endif
10570Sstevel@tonic-gate 			if (do_relocate(mp, rela, shtype, relasz/relaent,
10580Sstevel@tonic-gate 			    relaent, (Addr)mp->text) < 0)
10590Sstevel@tonic-gate 				return (-1);
10600Sstevel@tonic-gate 		} else {
10610Sstevel@tonic-gate 			if (do_relocations(mp) < 0)
10620Sstevel@tonic-gate 				return (-1);
10630Sstevel@tonic-gate 		}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 		/* sync_instruction_memory */
10660Sstevel@tonic-gate 		kobj_sync_instruction_memory(mp->text, mp->text_size);
10670Sstevel@tonic-gate 	}
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	for (lp = linkmap; lp; lp = lp->modl_next) {
10700Sstevel@tonic-gate 		mp = mod(lp);
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate 		/*
10730Sstevel@tonic-gate 		 * We need to re-read the full symbol table for the boot file,
10740Sstevel@tonic-gate 		 * since we couldn't use the full one before.  We also need to
10750Sstevel@tonic-gate 		 * load the CTF sections of both the boot file and the
10760Sstevel@tonic-gate 		 * interpreter (us).
10770Sstevel@tonic-gate 		 */
10780Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC) {
10790Sstevel@tonic-gate 			struct _buf *file;
10800Sstevel@tonic-gate 			int n;
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 			file = kobj_open_file(mp->filename);
10830Sstevel@tonic-gate 			if (file == (struct _buf *)-1)
10840Sstevel@tonic-gate 				return (-1);
10850Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)&mp->hdr,
10860Sstevel@tonic-gate 			    sizeof (mp->hdr), 0) < 0)
10870Sstevel@tonic-gate 				return (-1);
10880Sstevel@tonic-gate 			n = mp->hdr.e_shentsize * mp->hdr.e_shnum;
10890Sstevel@tonic-gate 			mp->shdrs = kobj_alloc(n, KM_WAIT);
10900Sstevel@tonic-gate 			if (kobj_read_file(file, mp->shdrs, n,
10910Sstevel@tonic-gate 			    mp->hdr.e_shoff) < 0)
10920Sstevel@tonic-gate 				return (-1);
10930Sstevel@tonic-gate 			if (get_syms(mp, file) < 0)
10940Sstevel@tonic-gate 				return (-1);
10950Sstevel@tonic-gate 			if (get_ctf(mp, file) < 0)
10960Sstevel@tonic-gate 				return (-1);
10970Sstevel@tonic-gate 			kobj_close_file(file);
10980Sstevel@tonic-gate 			mp->flags |= KOBJ_RELOCATED;
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 		} else if (mp->flags & KOBJ_INTERP) {
11010Sstevel@tonic-gate 			struct _buf *file;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 			/*
11040Sstevel@tonic-gate 			 * The interpreter path fragment in mp->filename
11050Sstevel@tonic-gate 			 * will already have the module directory suffix
11060Sstevel@tonic-gate 			 * in it (if appropriate).
11070Sstevel@tonic-gate 			 */
11080Sstevel@tonic-gate 			file = kobj_open_path(mp->filename, 1, 0);
11090Sstevel@tonic-gate 			if (file == (struct _buf *)-1)
11100Sstevel@tonic-gate 				return (-1);
11110Sstevel@tonic-gate 			if (get_ctf(mp, file) < 0)
11120Sstevel@tonic-gate 				return (-1);
11130Sstevel@tonic-gate 			kobj_close_file(file);
11140Sstevel@tonic-gate 			mp->flags |= KOBJ_RELOCATED;
11150Sstevel@tonic-gate 		}
11160Sstevel@tonic-gate 	}
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 	return (0);
11190Sstevel@tonic-gate }
11200Sstevel@tonic-gate 
11210Sstevel@tonic-gate static struct modctl *
11220Sstevel@tonic-gate mod_already_loaded(char *modname)
11230Sstevel@tonic-gate {
11240Sstevel@tonic-gate 	struct modctl *mctl = kobj_modules;
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	do {
11270Sstevel@tonic-gate 		if (strcmp(modname, mctl->mod_filename) == 0)
11280Sstevel@tonic-gate 			return (mctl);
11290Sstevel@tonic-gate 		mctl = mctl->mod_next;
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	} while (mctl != kobj_modules);
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 	return (NULL);
11340Sstevel@tonic-gate }
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate /*
11370Sstevel@tonic-gate  * Load all the primary dependent modules.
11380Sstevel@tonic-gate  */
11390Sstevel@tonic-gate static int
11400Sstevel@tonic-gate load_primary(struct module *mp, int lmid)
11410Sstevel@tonic-gate {
11420Sstevel@tonic-gate 	struct modctl *cp;
11430Sstevel@tonic-gate 	struct module *dmp;
11440Sstevel@tonic-gate 	char *p, *q;
11450Sstevel@tonic-gate 	char modname[MODMAXNAMELEN];
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	if ((p = mp->depends_on) == NULL)
11480Sstevel@tonic-gate 		return (0);
11490Sstevel@tonic-gate 
11500Sstevel@tonic-gate 	/* CONSTANTCONDITION */
11510Sstevel@tonic-gate 	while (1) {
11520Sstevel@tonic-gate 		/*
11530Sstevel@tonic-gate 		 * Skip space.
11540Sstevel@tonic-gate 		 */
11550Sstevel@tonic-gate 		while (*p && (*p == ' ' || *p == '\t'))
11560Sstevel@tonic-gate 			p++;
11570Sstevel@tonic-gate 		/*
11580Sstevel@tonic-gate 		 * Get module name.
11590Sstevel@tonic-gate 		 */
11600Sstevel@tonic-gate 		q = modname;
11610Sstevel@tonic-gate 		while (*p && *p != ' ' && *p != '\t')
11620Sstevel@tonic-gate 			*q++ = *p++;
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 		if (q == modname)
11650Sstevel@tonic-gate 			break;
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 		*q = '\0';
11680Sstevel@tonic-gate 		/*
11690Sstevel@tonic-gate 		 * Check for dup dependencies.
11700Sstevel@tonic-gate 		 */
11710Sstevel@tonic-gate 		if (strcmp(modname, "dtracestubs") == 0 ||
11720Sstevel@tonic-gate 		    mod_already_loaded(modname) != NULL)
11730Sstevel@tonic-gate 			continue;
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 		cp = add_primary(modname, lmid);
11760Sstevel@tonic-gate 		cp->mod_busy = 1;
11770Sstevel@tonic-gate 		/*
11780Sstevel@tonic-gate 		 * Load it.
11790Sstevel@tonic-gate 		 */
11800Sstevel@tonic-gate 		(void) kobj_load_module(cp, 1);
11810Sstevel@tonic-gate 		cp->mod_busy = 0;
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 		if ((dmp = cp->mod_mp) == NULL) {
11840Sstevel@tonic-gate 			cp->mod_loaded = 0;
11850Sstevel@tonic-gate 			cp->mod_installed = 0;
11860Sstevel@tonic-gate 			cp->mod_loadcnt = 0;
11870Sstevel@tonic-gate 			return (-1);
11880Sstevel@tonic-gate 		}
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 		add_dependent(mp, dmp);
11910Sstevel@tonic-gate 		dmp->flags |= KOBJ_PRIM;
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 		/*
11940Sstevel@tonic-gate 		 * Recurse.
11950Sstevel@tonic-gate 		 */
11960Sstevel@tonic-gate 		if (load_primary(dmp, lmid) == -1) {
11970Sstevel@tonic-gate 			cp->mod_loaded = 0;
11980Sstevel@tonic-gate 			cp->mod_installed = 0;
11990Sstevel@tonic-gate 			cp->mod_loadcnt = 0;
12000Sstevel@tonic-gate 			return (-1);
12010Sstevel@tonic-gate 		}
12020Sstevel@tonic-gate 	}
12030Sstevel@tonic-gate 	return (0);
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate static int
12070Sstevel@tonic-gate load_kmdb(val_t *bootaux)
12080Sstevel@tonic-gate {
12090Sstevel@tonic-gate 	struct modctl *mctl;
12100Sstevel@tonic-gate 	struct module *mp;
12110Sstevel@tonic-gate 	Sym *sym;
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	_kobj_printf(ops, "Loading kmdb...\n");
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 	if ((mctl = add_primary("misc/kmdbmod", KOBJ_LM_DEBUGGER)) == NULL)
12160Sstevel@tonic-gate 		return (-1);
12170Sstevel@tonic-gate 
12180Sstevel@tonic-gate 	mctl->mod_busy = 1;
12190Sstevel@tonic-gate 	(void) kobj_load_module(mctl, 1);
12200Sstevel@tonic-gate 	mctl->mod_busy = 0;
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	if ((mp = mctl->mod_mp) == NULL)
12230Sstevel@tonic-gate 		return (-1);
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	mp->flags |= KOBJ_PRIM;
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	if (load_primary(mp, KOBJ_LM_DEBUGGER) < 0)
12280Sstevel@tonic-gate 		return (-1);
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	if (boothowto & RB_VERBOSE)
12310Sstevel@tonic-gate 		kobj_lm_dump(KOBJ_LM_DEBUGGER);
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	if (bind_primary(bootaux, KOBJ_LM_DEBUGGER) < 0)
12340Sstevel@tonic-gate 		return (-1);
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 	if ((sym = lookup_one(mctl->mod_mp, "kctl_boot_activate")) == NULL)
12370Sstevel@tonic-gate 		return (-1);
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate 	if (((kctl_boot_activate_f *)sym->st_value)(ops, romp, 0,
12400Sstevel@tonic-gate 	    (const char **)kobj_kmdb_argv) < 0)
12410Sstevel@tonic-gate 		return (-1);
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate 	return (0);
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate /*
12470Sstevel@tonic-gate  * Return a string listing module dependencies.
12480Sstevel@tonic-gate  */
12490Sstevel@tonic-gate static char *
12500Sstevel@tonic-gate depends_on(struct module *mp)
12510Sstevel@tonic-gate {
12520Sstevel@tonic-gate 	Sym *sp;
12530Sstevel@tonic-gate 	char *depstr, *q;
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	/*
12560Sstevel@tonic-gate 	 * The module doesn't have a depends_on value, so let's try it the
12570Sstevel@tonic-gate 	 * old-fashioned way - via "_depends_on"
12580Sstevel@tonic-gate 	 */
12590Sstevel@tonic-gate 	if ((sp = lookup_one(mp, "_depends_on")) == NULL)
12600Sstevel@tonic-gate 		return (NULL);
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	q = (char *)sp->st_value;
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 	/*
12650Sstevel@tonic-gate 	 * Idiot checks. Make sure it's
12660Sstevel@tonic-gate 	 * in-bounds and NULL terminated.
12670Sstevel@tonic-gate 	 */
12680Sstevel@tonic-gate 	if (kobj_addrcheck(mp, q) || q[sp->st_size - 1] != '\0') {
12690Sstevel@tonic-gate 		_kobj_printf(ops, "Error processing dependency for %s\n",
12700Sstevel@tonic-gate 		    mp->filename);
12710Sstevel@tonic-gate 		return (NULL);
12720Sstevel@tonic-gate 	}
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate 	depstr = (char *)kobj_alloc(strlen(q) + 1, KM_WAIT);
12750Sstevel@tonic-gate 	(void) strcpy(depstr, q);
12760Sstevel@tonic-gate 
12770Sstevel@tonic-gate 	return (depstr);
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate void
12810Sstevel@tonic-gate kobj_getmodinfo(void *xmp, struct modinfo *modinfo)
12820Sstevel@tonic-gate {
12830Sstevel@tonic-gate 	struct module *mp;
12840Sstevel@tonic-gate 	mp = (struct module *)xmp;
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate 	modinfo->mi_base = mp->text;
12870Sstevel@tonic-gate 	modinfo->mi_size = mp->text_size + mp->data_size;
12880Sstevel@tonic-gate }
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate /*
12910Sstevel@tonic-gate  * kobj_export_ksyms() performs the following services:
12920Sstevel@tonic-gate  *
12930Sstevel@tonic-gate  * (1) Migrates the symbol table from boot/kobj memory to the ksyms arena.
12940Sstevel@tonic-gate  * (2) Removes unneeded symbols to save space.
12950Sstevel@tonic-gate  * (3) Reduces memory footprint by using VM_BESTFIT allocations.
12960Sstevel@tonic-gate  * (4) Makes the symbol table visible to /dev/ksyms.
12970Sstevel@tonic-gate  */
12980Sstevel@tonic-gate static void
12990Sstevel@tonic-gate kobj_export_ksyms(struct module *mp)
13000Sstevel@tonic-gate {
13010Sstevel@tonic-gate 	Sym *esp = (Sym *)(mp->symtbl + mp->symhdr->sh_size);
13020Sstevel@tonic-gate 	Sym *sp, *osp;
13030Sstevel@tonic-gate 	char *name;
13040Sstevel@tonic-gate 	size_t namelen;
13050Sstevel@tonic-gate 	struct module *omp;
13060Sstevel@tonic-gate 	uint_t nsyms;
13070Sstevel@tonic-gate 	size_t symsize = mp->symhdr->sh_entsize;
13080Sstevel@tonic-gate 	size_t locals = 1;
13090Sstevel@tonic-gate 	size_t strsize;
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	/*
13120Sstevel@tonic-gate 	 * Make a copy of the original module structure.
13130Sstevel@tonic-gate 	 */
13140Sstevel@tonic-gate 	omp = kobj_alloc(sizeof (struct module), KM_WAIT);
13150Sstevel@tonic-gate 	bcopy(mp, omp, sizeof (struct module));
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 	/*
13180Sstevel@tonic-gate 	 * Compute the sizes of the new symbol table sections.
13190Sstevel@tonic-gate 	 */
13200Sstevel@tonic-gate 	for (nsyms = strsize = 1, osp = (Sym *)omp->symtbl; osp < esp; osp++) {
13210Sstevel@tonic-gate 		if (osp->st_value == 0)
13220Sstevel@tonic-gate 			continue;
13230Sstevel@tonic-gate 		if (sym_lookup(omp, osp) == NULL)
13240Sstevel@tonic-gate 			continue;
13250Sstevel@tonic-gate 		name = omp->strings + osp->st_name;
13260Sstevel@tonic-gate 		namelen = strlen(name);
13270Sstevel@tonic-gate 		if (ELF_ST_BIND(osp->st_info) == STB_LOCAL)
13280Sstevel@tonic-gate 			locals++;
13290Sstevel@tonic-gate 		nsyms++;
13300Sstevel@tonic-gate 		strsize += namelen + 1;
13310Sstevel@tonic-gate 	}
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	mp->nsyms = nsyms;
13340Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 	/*
13370Sstevel@tonic-gate 	 * ksyms_lock must be held as writer during any operation that
13380Sstevel@tonic-gate 	 * modifies ksyms_arena, including allocation from same, and
13390Sstevel@tonic-gate 	 * must not be dropped until the arena is vmem_walk()able.
13400Sstevel@tonic-gate 	 */
13410Sstevel@tonic-gate 	rw_enter(&ksyms_lock, RW_WRITER);
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	/*
13440Sstevel@tonic-gate 	 * Allocate space for the new section headers (symtab and strtab),
13450Sstevel@tonic-gate 	 * symbol table, buckets, chains, and strings.
13460Sstevel@tonic-gate 	 */
13470Sstevel@tonic-gate 	mp->symsize = (2 * sizeof (Shdr)) + (nsyms * symsize) +
13480Sstevel@tonic-gate 	    (mp->hashsize + mp->nsyms) * sizeof (symid_t) + strsize;
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	if (mp->flags & KOBJ_NOKSYMS) {
13510Sstevel@tonic-gate 		mp->symspace = kobj_alloc(mp->symsize, KM_WAIT);
13520Sstevel@tonic-gate 	} else {
13530Sstevel@tonic-gate 		mp->symspace = vmem_alloc(ksyms_arena, mp->symsize,
13540Sstevel@tonic-gate 		    VM_BESTFIT | VM_SLEEP);
13550Sstevel@tonic-gate 	}
13560Sstevel@tonic-gate 	bzero(mp->symspace, mp->symsize);
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 	/*
13590Sstevel@tonic-gate 	 * Divvy up symspace.
13600Sstevel@tonic-gate 	 */
13610Sstevel@tonic-gate 	mp->shdrs = mp->symspace;
13620Sstevel@tonic-gate 	mp->symhdr = (Shdr *)mp->shdrs;
13630Sstevel@tonic-gate 	mp->strhdr = (Shdr *)(mp->symhdr + 1);
13640Sstevel@tonic-gate 	mp->symtbl = (char *)(mp->strhdr + 1);
13650Sstevel@tonic-gate 	mp->buckets = (symid_t *)(mp->symtbl + (nsyms * symsize));
13660Sstevel@tonic-gate 	mp->chains = (symid_t *)(mp->buckets + mp->hashsize);
13670Sstevel@tonic-gate 	mp->strings = (char *)(mp->chains + nsyms);
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	/*
13700Sstevel@tonic-gate 	 * Fill in the new section headers (symtab and strtab).
13710Sstevel@tonic-gate 	 */
13720Sstevel@tonic-gate 	mp->hdr.e_shnum = 2;
13730Sstevel@tonic-gate 	mp->symtbl_section = 0;
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 	mp->symhdr->sh_type = SHT_SYMTAB;
13760Sstevel@tonic-gate 	mp->symhdr->sh_addr = (Addr)mp->symtbl;
13770Sstevel@tonic-gate 	mp->symhdr->sh_size = nsyms * symsize;
13780Sstevel@tonic-gate 	mp->symhdr->sh_link = 1;
13790Sstevel@tonic-gate 	mp->symhdr->sh_info = locals;
13800Sstevel@tonic-gate 	mp->symhdr->sh_addralign = sizeof (Addr);
13810Sstevel@tonic-gate 	mp->symhdr->sh_entsize = symsize;
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	mp->strhdr->sh_type = SHT_STRTAB;
13840Sstevel@tonic-gate 	mp->strhdr->sh_addr = (Addr)mp->strings;
13850Sstevel@tonic-gate 	mp->strhdr->sh_size = strsize;
13860Sstevel@tonic-gate 	mp->strhdr->sh_addralign = 1;
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 	/*
13890Sstevel@tonic-gate 	 * Construct the new symbol table.
13900Sstevel@tonic-gate 	 */
13910Sstevel@tonic-gate 	for (nsyms = strsize = 1, osp = (Sym *)omp->symtbl; osp < esp; osp++) {
13920Sstevel@tonic-gate 		if (osp->st_value == 0)
13930Sstevel@tonic-gate 			continue;
13940Sstevel@tonic-gate 		if (sym_lookup(omp, osp) == NULL)
13950Sstevel@tonic-gate 			continue;
13960Sstevel@tonic-gate 		name = omp->strings + osp->st_name;
13970Sstevel@tonic-gate 		namelen = strlen(name);
13980Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + symsize * nsyms);
13990Sstevel@tonic-gate 		bcopy(osp, sp, symsize);
14000Sstevel@tonic-gate 		bcopy(name, mp->strings + strsize, namelen);
14010Sstevel@tonic-gate 		sp->st_name = strsize;
14020Sstevel@tonic-gate 		sym_insert(mp, name, nsyms);
14030Sstevel@tonic-gate 		nsyms++;
14040Sstevel@tonic-gate 		strsize += namelen + 1;
14050Sstevel@tonic-gate 	}
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 	rw_exit(&ksyms_lock);
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	/*
14100Sstevel@tonic-gate 	 * Free the old section headers -- we'll never need them again.
14110Sstevel@tonic-gate 	 */
14120Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_PRIM))
14130Sstevel@tonic-gate 		kobj_free(omp->shdrs, omp->hdr.e_shentsize * omp->hdr.e_shnum);
14140Sstevel@tonic-gate 	/*
14150Sstevel@tonic-gate 	 * Discard the old symbol table and our copy of the module strucure.
14160Sstevel@tonic-gate 	 */
14170Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_PRIM))
14180Sstevel@tonic-gate 		kobj_free(omp->symspace, omp->symsize);
14190Sstevel@tonic-gate 	kobj_free(omp, sizeof (struct module));
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate static void
14230Sstevel@tonic-gate kobj_export_ctf(struct module *mp)
14240Sstevel@tonic-gate {
14250Sstevel@tonic-gate 	char *data = mp->ctfdata;
14260Sstevel@tonic-gate 	size_t size = mp->ctfsize;
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	if (data != NULL) {
14290Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_NOCTF) {
14300Sstevel@tonic-gate 			mp->ctfdata = NULL;
14310Sstevel@tonic-gate 			mp->ctfsize = 0;
14320Sstevel@tonic-gate 		} else {
14330Sstevel@tonic-gate 			mp->ctfdata = vmem_alloc(ctf_arena, size,
14340Sstevel@tonic-gate 			    VM_BESTFIT | VM_SLEEP);
14350Sstevel@tonic-gate 			bcopy(data, mp->ctfdata, size);
14360Sstevel@tonic-gate 		}
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_PRIM))
14390Sstevel@tonic-gate 			kobj_free(data, size);
14400Sstevel@tonic-gate 	}
14410Sstevel@tonic-gate }
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate void
14440Sstevel@tonic-gate kobj_export_module(struct module *mp)
14450Sstevel@tonic-gate {
14460Sstevel@tonic-gate 	kobj_export_ksyms(mp);
14470Sstevel@tonic-gate 	kobj_export_ctf(mp);
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	mp->flags |= KOBJ_EXPORTED;
14500Sstevel@tonic-gate }
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate static int
14530Sstevel@tonic-gate process_dynamic(struct module *mp, char *dyndata, char *strdata)
14540Sstevel@tonic-gate {
14550Sstevel@tonic-gate 	char *path = NULL, *depstr = NULL;
14560Sstevel@tonic-gate 	int allocsize = 0, osize = 0, nsize = 0;
14570Sstevel@tonic-gate 	char *libname, *tmp;
14580Sstevel@tonic-gate 	int lsize;
14590Sstevel@tonic-gate 	Dyn *dynp;
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate 	for (dynp = (Dyn *)dyndata; dynp && dynp->d_tag != DT_NULL; dynp++) {
14620Sstevel@tonic-gate 		switch (dynp->d_tag) {
14630Sstevel@tonic-gate 		case DT_NEEDED:
14640Sstevel@tonic-gate 			/*
14650Sstevel@tonic-gate 			 * Read the DT_NEEDED entries, expanding the macros they
14660Sstevel@tonic-gate 			 * contain (if any), and concatenating them into a
14670Sstevel@tonic-gate 			 * single space-separated dependency list.
14680Sstevel@tonic-gate 			 */
14690Sstevel@tonic-gate 			libname = (ulong_t)dynp->d_un.d_ptr + strdata;
14700Sstevel@tonic-gate 
14710Sstevel@tonic-gate 			if (strchr(libname, '$') != NULL) {
14720Sstevel@tonic-gate 				char *_lib;
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 				if (path == NULL)
14750Sstevel@tonic-gate 					path = kobj_alloc(MAXPATHLEN, KM_WAIT);
14760Sstevel@tonic-gate 				if ((_lib = expand_libmacro(libname, path,
14770Sstevel@tonic-gate 				    path)) != NULL)
14780Sstevel@tonic-gate 					libname = _lib;
14790Sstevel@tonic-gate 				else {
14800Sstevel@tonic-gate 					_kobj_printf(ops, "krtld: "
14810Sstevel@tonic-gate 					    "process_dynamic: failed to expand "
14820Sstevel@tonic-gate 					    "%s\n", libname);
14830Sstevel@tonic-gate 				}
14840Sstevel@tonic-gate 			}
14850Sstevel@tonic-gate 
14860Sstevel@tonic-gate 			lsize = strlen(libname);
14870Sstevel@tonic-gate 			nsize += lsize;
14880Sstevel@tonic-gate 			if (nsize + 1 > allocsize) {
14890Sstevel@tonic-gate 				tmp = kobj_alloc(allocsize + MAXPATHLEN,
14900Sstevel@tonic-gate 				    KM_WAIT);
14910Sstevel@tonic-gate 				if (depstr != NULL) {
14920Sstevel@tonic-gate 					bcopy(depstr, tmp, osize);
14930Sstevel@tonic-gate 					kobj_free(depstr, allocsize);
14940Sstevel@tonic-gate 				}
14950Sstevel@tonic-gate 				depstr = tmp;
14960Sstevel@tonic-gate 				allocsize += MAXPATHLEN;
14970Sstevel@tonic-gate 			}
14980Sstevel@tonic-gate 			bcopy(libname, depstr + osize, lsize);
14990Sstevel@tonic-gate 			*(depstr + nsize) = ' '; /* separator */
15000Sstevel@tonic-gate 			nsize++;
15010Sstevel@tonic-gate 			osize = nsize;
15020Sstevel@tonic-gate 			break;
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 		case DT_FLAGS_1:
15050Sstevel@tonic-gate 			if (dynp->d_un.d_val & DF_1_IGNMULDEF)
15060Sstevel@tonic-gate 				mp->flags |= KOBJ_IGNMULDEF;
15070Sstevel@tonic-gate 			if (dynp->d_un.d_val & DF_1_NOKSYMS)
15080Sstevel@tonic-gate 				mp->flags |= KOBJ_NOKSYMS;
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate 			break;
15110Sstevel@tonic-gate 		}
15120Sstevel@tonic-gate 	}
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 	/*
15150Sstevel@tonic-gate 	 * finish up the depends string (if any)
15160Sstevel@tonic-gate 	 */
15170Sstevel@tonic-gate 	if (depstr != NULL) {
15180Sstevel@tonic-gate 		*(depstr + nsize - 1) = '\0'; /* overwrite seperator w/term */
15190Sstevel@tonic-gate 		if (path != NULL)
15200Sstevel@tonic-gate 			kobj_free(path, MAXPATHLEN);
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate 		tmp = kobj_alloc(nsize, KM_WAIT);
15230Sstevel@tonic-gate 		bcopy(depstr, tmp, nsize);
15240Sstevel@tonic-gate 		kobj_free(depstr, allocsize);
15250Sstevel@tonic-gate 		depstr = tmp;
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate 		mp->depends_on = depstr;
15280Sstevel@tonic-gate 	}
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	return (0);
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate 
15330Sstevel@tonic-gate static int
15340Sstevel@tonic-gate do_dynamic(struct module *mp, struct _buf *file)
15350Sstevel@tonic-gate {
15360Sstevel@tonic-gate 	Shdr *dshp, *dstrp, *shp;
15370Sstevel@tonic-gate 	char *dyndata, *dstrdata;
15380Sstevel@tonic-gate 	int dshn, shn, rc;
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 	/* find and validate the dynamic section (if any) */
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	for (dshp = NULL, shn = 1; shn < mp->hdr.e_shnum; shn++) {
15430Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
15440Sstevel@tonic-gate 		switch (shp->sh_type) {
15450Sstevel@tonic-gate 		case SHT_DYNAMIC:
15460Sstevel@tonic-gate 			if (dshp != NULL) {
15470Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_dynamic: %s, ",
15480Sstevel@tonic-gate 				    mp->filename);
15490Sstevel@tonic-gate 				_kobj_printf(ops,
15500Sstevel@tonic-gate 				    "multiple dynamic sections\n");
15510Sstevel@tonic-gate 				return (-1);
15520Sstevel@tonic-gate 			} else {
15530Sstevel@tonic-gate 				dshp = shp;
15540Sstevel@tonic-gate 				dshn = shn;
15550Sstevel@tonic-gate 			}
15560Sstevel@tonic-gate 			break;
15570Sstevel@tonic-gate 		}
15580Sstevel@tonic-gate 	}
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	if (dshp == NULL)
15610Sstevel@tonic-gate 		return (0);
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 	if (dshp->sh_link > mp->hdr.e_shnum) {
15640Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
15650Sstevel@tonic-gate 		_kobj_printf(ops, "no section for sh_link %d\n", dshp->sh_link);
15660Sstevel@tonic-gate 		return (-1);
15670Sstevel@tonic-gate 	}
15680Sstevel@tonic-gate 	dstrp = (Shdr *)(mp->shdrs + dshp->sh_link * mp->hdr.e_shentsize);
15690Sstevel@tonic-gate 
15700Sstevel@tonic-gate 	if (dstrp->sh_type != SHT_STRTAB) {
15710Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
15720Sstevel@tonic-gate 		_kobj_printf(ops, "sh_link not a string table for section %d\n",
15730Sstevel@tonic-gate 		    dshn);
15740Sstevel@tonic-gate 		return (-1);
15750Sstevel@tonic-gate 	}
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 	/* read it from disk */
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 	dyndata = kobj_alloc(dshp->sh_size, KM_WAIT|KM_TMP);
15800Sstevel@tonic-gate 	if (kobj_read_file(file, dyndata, dshp->sh_size, dshp->sh_offset) < 0) {
15810Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
15820Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %d\n", dshn);
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 		kobj_free(dyndata, dshp->sh_size);
15850Sstevel@tonic-gate 		return (-1);
15860Sstevel@tonic-gate 	}
15870Sstevel@tonic-gate 
15880Sstevel@tonic-gate 	dstrdata = kobj_alloc(dstrp->sh_size, KM_WAIT|KM_TMP);
15890Sstevel@tonic-gate 	if (kobj_read_file(file, dstrdata, dstrp->sh_size,
15900Sstevel@tonic-gate 	    dstrp->sh_offset) < 0) {
15910Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_dynamic: %s, ", mp->filename);
15920Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %d\n", dshp->sh_link);
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 		kobj_free(dyndata, dshp->sh_size);
15950Sstevel@tonic-gate 		kobj_free(dstrdata, dstrp->sh_size);
15960Sstevel@tonic-gate 		return (-1);
15970Sstevel@tonic-gate 	}
15980Sstevel@tonic-gate 
15990Sstevel@tonic-gate 	/* pull the interesting pieces out */
16000Sstevel@tonic-gate 
16010Sstevel@tonic-gate 	rc = process_dynamic(mp, dyndata, dstrdata);
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 	kobj_free(dyndata, dshp->sh_size);
16040Sstevel@tonic-gate 	kobj_free(dstrdata, dstrp->sh_size);
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	return (rc);
16070Sstevel@tonic-gate }
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate void
16100Sstevel@tonic-gate kobj_set_ctf(struct module *mp, caddr_t data, size_t size)
16110Sstevel@tonic-gate {
16120Sstevel@tonic-gate 	if (!standalone) {
16130Sstevel@tonic-gate 		if (mp->ctfdata != NULL) {
16140Sstevel@tonic-gate 			if (vmem_contains(ctf_arena, mp->ctfdata,
16150Sstevel@tonic-gate 				mp->ctfsize)) {
16160Sstevel@tonic-gate 				vmem_free(ctf_arena, mp->ctfdata, mp->ctfsize);
16170Sstevel@tonic-gate 			} else {
16180Sstevel@tonic-gate 				kobj_free(mp->ctfdata, mp->ctfsize);
16190Sstevel@tonic-gate 			}
16200Sstevel@tonic-gate 		}
16210Sstevel@tonic-gate 	}
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 	/*
16240Sstevel@tonic-gate 	 * The order is very important here.  We need to make sure that
16250Sstevel@tonic-gate 	 * consumers, at any given instant, see a consistent state.  We'd
16260Sstevel@tonic-gate 	 * rather they see no CTF data than the address of one buffer and the
16270Sstevel@tonic-gate 	 * size of another.
16280Sstevel@tonic-gate 	 */
16290Sstevel@tonic-gate 	mp->ctfdata = NULL;
16300Sstevel@tonic-gate 	membar_producer();
16310Sstevel@tonic-gate 	mp->ctfsize = size;
16320Sstevel@tonic-gate 	mp->ctfdata = data;
16330Sstevel@tonic-gate 	membar_producer();
16340Sstevel@tonic-gate }
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate int
16370Sstevel@tonic-gate kobj_load_module(struct modctl *modp, int use_path)
16380Sstevel@tonic-gate {
16390Sstevel@tonic-gate 	char *filename = modp->mod_filename;
16400Sstevel@tonic-gate 	char *modname = modp->mod_modname;
16410Sstevel@tonic-gate 	int i;
16420Sstevel@tonic-gate 	int n;
16430Sstevel@tonic-gate 	struct _buf *file;
16440Sstevel@tonic-gate 	struct module *mp = NULL;
16450Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
16460Sstevel@tonic-gate 	int no_suffixdir_drv = 0;
16470Sstevel@tonic-gate #endif
16480Sstevel@tonic-gate 
16490Sstevel@tonic-gate 	mp = kobj_zalloc(sizeof (struct module), KM_WAIT);
16500Sstevel@tonic-gate 
16510Sstevel@tonic-gate 	/*
16520Sstevel@tonic-gate 	 * We need to prevent kmdb's symbols from leaking into /dev/ksyms.
16530Sstevel@tonic-gate 	 * kmdb contains a bunch of symbols with well-known names, symbols
16540Sstevel@tonic-gate 	 * which will mask the real versions, thus causing no end of trouble
16550Sstevel@tonic-gate 	 * for mdb.
16560Sstevel@tonic-gate 	 */
16570Sstevel@tonic-gate 	if (strcmp(modp->mod_modname, "kmdbmod") == 0)
16580Sstevel@tonic-gate 		mp->flags |= KOBJ_NOKSYMS;
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate 	file = kobj_open_path(filename, use_path, 1);
16610Sstevel@tonic-gate 	if (file == (struct _buf *)-1) {
16620Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
16630Sstevel@tonic-gate 		file = kobj_open_path(filename, use_path, 0);
16640Sstevel@tonic-gate #endif
16650Sstevel@tonic-gate 		if (file == (struct _buf *)-1) {
16660Sstevel@tonic-gate 			kobj_free(mp, sizeof (*mp));
16670Sstevel@tonic-gate 			goto bad;
16680Sstevel@tonic-gate 		}
16690Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
16700Sstevel@tonic-gate 		/*
16710Sstevel@tonic-gate 		 * There is no driver module in the ISA specific (suffix)
16720Sstevel@tonic-gate 		 * subdirectory but there is a module in the parent directory.
16730Sstevel@tonic-gate 		 */
16740Sstevel@tonic-gate 		if (strncmp(filename, "drv/", 4) == 0) {
16750Sstevel@tonic-gate 			no_suffixdir_drv = 1;
16760Sstevel@tonic-gate 		}
16770Sstevel@tonic-gate #endif
16780Sstevel@tonic-gate 	}
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	mp->filename = kobj_alloc(strlen(file->_name) + 1, KM_WAIT);
16810Sstevel@tonic-gate 	(void) strcpy(mp->filename, file->_name);
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 	if (kobj_read_file(file, (char *)&mp->hdr, sizeof (mp->hdr), 0) < 0) {
16840Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_load_module: %s read header failed\n",
16850Sstevel@tonic-gate 		    modname);
16860Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
16870Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
16880Sstevel@tonic-gate 		goto bad;
16890Sstevel@tonic-gate 	}
16900Sstevel@tonic-gate 	for (i = 0; i < SELFMAG; i++) {
16910Sstevel@tonic-gate 		if (mp->hdr.e_ident[i] != ELFMAG[i]) {
16920Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG)
16930Sstevel@tonic-gate 				_kobj_printf(ops, "%s not an elf module\n",
16940Sstevel@tonic-gate 				    modname);
16950Sstevel@tonic-gate 			kobj_free(mp->filename, strlen(file->_name) + 1);
16960Sstevel@tonic-gate 			kobj_free(mp, sizeof (*mp));
16970Sstevel@tonic-gate 			goto bad;
16980Sstevel@tonic-gate 		}
16990Sstevel@tonic-gate 	}
17000Sstevel@tonic-gate 	/*
17010Sstevel@tonic-gate 	 * It's ELF, but is it our ISA?  Interpreting the header
17020Sstevel@tonic-gate 	 * from a file for a byte-swapped ISA could cause a huge
17030Sstevel@tonic-gate 	 * and unsatisfiable value to be passed to kobj_alloc below
17040Sstevel@tonic-gate 	 * and therefore hang booting.
17050Sstevel@tonic-gate 	 */
17060Sstevel@tonic-gate 	if (!elf_mach_ok(&mp->hdr)) {
17070Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG)
17080Sstevel@tonic-gate 			_kobj_printf(ops, "%s not an elf module for this ISA\n",
17090Sstevel@tonic-gate 			    modname);
17100Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
17110Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
17120Sstevel@tonic-gate #ifdef MODDIR_SUFFIX
17130Sstevel@tonic-gate 		/*
17140Sstevel@tonic-gate 		 * The driver mod is not in the ISA specific subdirectory
17150Sstevel@tonic-gate 		 * and the module in the parent directory is not our ISA.
17160Sstevel@tonic-gate 		 * If it is our ISA, for now we will silently succeed.
17170Sstevel@tonic-gate 		 */
17180Sstevel@tonic-gate 		if (no_suffixdir_drv == 1) {
17190Sstevel@tonic-gate 			cmn_err(CE_CONT, "?NOTICE: %s: 64-bit driver module"
17200Sstevel@tonic-gate 			    " not found\n", modname);
17210Sstevel@tonic-gate 		}
17220Sstevel@tonic-gate #endif
17230Sstevel@tonic-gate 		goto bad;
17240Sstevel@tonic-gate 	}
17250Sstevel@tonic-gate 
17260Sstevel@tonic-gate 	/*
17270Sstevel@tonic-gate 	 * All modules, save for unix, should be relocatable (as opposed to
17280Sstevel@tonic-gate 	 * dynamic).  Dynamic modules come with PLTs and GOTs, which can't
17290Sstevel@tonic-gate 	 * currently be processed by krtld.
17300Sstevel@tonic-gate 	 */
17310Sstevel@tonic-gate 	if (mp->hdr.e_type != ET_REL) {
17320Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG)
17330Sstevel@tonic-gate 			_kobj_printf(ops, "%s isn't a relocatable (ET_REL) "
17340Sstevel@tonic-gate 			    "module\n", modname);
17350Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
17360Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
17370Sstevel@tonic-gate 		goto bad;
17380Sstevel@tonic-gate 	}
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate 	n = mp->hdr.e_shentsize * mp->hdr.e_shnum;
17410Sstevel@tonic-gate 	mp->shdrs = kobj_alloc(n, KM_WAIT);
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	if (kobj_read_file(file, mp->shdrs, n, mp->hdr.e_shoff) < 0) {
17440Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_load_module: %s error reading "
17450Sstevel@tonic-gate 		    "section headers\n", modname);
17460Sstevel@tonic-gate 		kobj_free(mp->shdrs, n);
17470Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(file->_name) + 1);
17480Sstevel@tonic-gate 		kobj_free(mp, sizeof (*mp));
17490Sstevel@tonic-gate 		goto bad;
17500Sstevel@tonic-gate 	}
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODLOADING, modp);
17530Sstevel@tonic-gate 	module_assign(modp, mp);
17540Sstevel@tonic-gate 
17550Sstevel@tonic-gate 	/* read in sections */
17560Sstevel@tonic-gate 	if (get_progbits(mp, file) < 0) {
17570Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading sections\n", modname);
17580Sstevel@tonic-gate 		goto bad;
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	if (do_dynamic(mp, file) < 0) {
17620Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading dynamic section\n",
17630Sstevel@tonic-gate 		    modname);
17640Sstevel@tonic-gate 		goto bad;
17650Sstevel@tonic-gate 	}
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 	modp->mod_text = mp->text;
17680Sstevel@tonic-gate 	modp->mod_text_size = mp->text_size;
17690Sstevel@tonic-gate 
17700Sstevel@tonic-gate 	/* read in symbols; adjust values for each section's real address */
17710Sstevel@tonic-gate 	if (get_syms(mp, file) < 0) {
17720Sstevel@tonic-gate 		_kobj_printf(ops, "%s error reading symbols\n",
17730Sstevel@tonic-gate 		    modname);
17740Sstevel@tonic-gate 		goto bad;
17750Sstevel@tonic-gate 	}
17760Sstevel@tonic-gate 
17770Sstevel@tonic-gate 	/*
17780Sstevel@tonic-gate 	 * If we didn't dependency information from the dynamic section, look
17790Sstevel@tonic-gate 	 * for it the old-fashioned way.
17800Sstevel@tonic-gate 	 */
17810Sstevel@tonic-gate 	if (mp->depends_on == NULL)
17820Sstevel@tonic-gate 		mp->depends_on = depends_on(mp);
17830Sstevel@tonic-gate 
17840Sstevel@tonic-gate 	if (get_ctf(mp, file) < 0) {
17850Sstevel@tonic-gate 		_kobj_printf(ops, "%s debug information will not "
17860Sstevel@tonic-gate 		    "be available\n", modname);
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	/* primary kernel modules do not have a signature section */
17900Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_PRIM))
17910Sstevel@tonic-gate 		get_signature(mp, file);
17920Sstevel@tonic-gate 
17930Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
17940Sstevel@tonic-gate 	if (kobj_debug & D_LOADING) {
17950Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: file=%s\n", mp->filename);
17960Sstevel@tonic-gate 		_kobj_printf(ops, "\ttext:0x%p", mp->text);
17970Sstevel@tonic-gate 		_kobj_printf(ops, " size: 0x%x\n", mp->text_size);
17980Sstevel@tonic-gate 		_kobj_printf(ops, "\tdata:0x%p", mp->data);
17990Sstevel@tonic-gate 		_kobj_printf(ops, " dsize: 0x%x\n", mp->data_size);
18000Sstevel@tonic-gate 	}
18010Sstevel@tonic-gate #endif /* KOBJ_DEBUG */
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	/*
18040Sstevel@tonic-gate 	 * For primary kernel modules, we defer
18050Sstevel@tonic-gate 	 * symbol resolution and relocation until
18060Sstevel@tonic-gate 	 * all primary objects have been loaded.
18070Sstevel@tonic-gate 	 */
18080Sstevel@tonic-gate 	if (!standalone) {
18090Sstevel@tonic-gate 		int ddrval, dcrval;
18100Sstevel@tonic-gate 		char *dependent_modname;
18110Sstevel@tonic-gate 		/* load all dependents */
18120Sstevel@tonic-gate 		dependent_modname = kobj_zalloc(MODMAXNAMELEN, KM_WAIT);
18130Sstevel@tonic-gate 		ddrval = do_dependents(modp, dependent_modname, MODMAXNAMELEN);
18140Sstevel@tonic-gate 
18150Sstevel@tonic-gate 		/*
18160Sstevel@tonic-gate 		 * resolve undefined and common symbols,
18170Sstevel@tonic-gate 		 * also allocates common space
18180Sstevel@tonic-gate 		 */
18190Sstevel@tonic-gate 		if ((dcrval = do_common(mp)) < 0) {
18200Sstevel@tonic-gate 			switch (dcrval) {
18210Sstevel@tonic-gate 			case DOSYM_UNSAFE:
18220Sstevel@tonic-gate 				_kobj_printf(ops, "WARNING: mod_load: "
18230Sstevel@tonic-gate 				    "MT-unsafe module '%s' rejected\n",
18240Sstevel@tonic-gate 				    modname);
18250Sstevel@tonic-gate 				break;
18260Sstevel@tonic-gate 			case DOSYM_UNDEF:
18270Sstevel@tonic-gate 				_kobj_printf(ops, "WARNING: mod_load: "
18280Sstevel@tonic-gate 				    "cannot load module '%s'\n",
18290Sstevel@tonic-gate 				    modname);
18300Sstevel@tonic-gate 				if (ddrval == -1) {
18310Sstevel@tonic-gate 					_kobj_printf(ops, "WARNING: %s: ",
18320Sstevel@tonic-gate 					    modname);
18330Sstevel@tonic-gate 					_kobj_printf(ops,
18340Sstevel@tonic-gate 					    "unable to resolve dependency, "
18350Sstevel@tonic-gate 					    "module '%s' not found\n",
18360Sstevel@tonic-gate 					    dependent_modname);
18370Sstevel@tonic-gate 				}
18380Sstevel@tonic-gate 				break;
18390Sstevel@tonic-gate 			}
18400Sstevel@tonic-gate 		}
18410Sstevel@tonic-gate 		kobj_free(dependent_modname, MODMAXNAMELEN);
18420Sstevel@tonic-gate 		if (dcrval < 0)
18430Sstevel@tonic-gate 			goto bad;
18440Sstevel@tonic-gate 
18450Sstevel@tonic-gate 		/* process relocation tables */
18460Sstevel@tonic-gate 		if (do_relocations(mp) < 0) {
18470Sstevel@tonic-gate 			_kobj_printf(ops, "%s error doing relocations\n",
18480Sstevel@tonic-gate 			    modname);
18490Sstevel@tonic-gate 			goto bad;
18500Sstevel@tonic-gate 		}
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 		if (mp->destination) {
18530Sstevel@tonic-gate 			off_t	off = (uintptr_t)mp->destination & PAGEOFFSET;
18540Sstevel@tonic-gate 			caddr_t	base = (caddr_t)mp->destination - off;
18550Sstevel@tonic-gate 			size_t	size = P2ROUNDUP(mp->text_size + off, PAGESIZE);
18560Sstevel@tonic-gate 
18570Sstevel@tonic-gate 			hat_unload(kas.a_hat, base, size, HAT_UNLOAD_UNLOCK);
18580Sstevel@tonic-gate 			vmem_free(heap_arena, base, size);
18590Sstevel@tonic-gate 		}
18600Sstevel@tonic-gate 
18610Sstevel@tonic-gate 		/* sync_instruction_memory */
18620Sstevel@tonic-gate 		kobj_sync_instruction_memory(mp->text, mp->text_size);
18630Sstevel@tonic-gate #ifdef	MPSAS
18640Sstevel@tonic-gate 		sas_syms(mp);
18650Sstevel@tonic-gate #endif
18660Sstevel@tonic-gate 		kobj_export_module(mp);
18670Sstevel@tonic-gate 		kobj_notify(KOBJ_NOTIFY_MODLOADED, modp);
18680Sstevel@tonic-gate 	}
18690Sstevel@tonic-gate 	kobj_close_file(file);
18700Sstevel@tonic-gate 	return (0);
18710Sstevel@tonic-gate bad:
18720Sstevel@tonic-gate 	if (file != (struct _buf *)-1)
18730Sstevel@tonic-gate 		kobj_close_file(file);
18740Sstevel@tonic-gate 	if (modp->mod_mp != NULL)
18750Sstevel@tonic-gate 		free_module_data(modp->mod_mp);
18760Sstevel@tonic-gate 
18770Sstevel@tonic-gate 	module_assign(modp, NULL);
18780Sstevel@tonic-gate 	return ((file == (struct _buf *)-1) ? ENOENT : EINVAL);
18790Sstevel@tonic-gate }
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate int
18820Sstevel@tonic-gate kobj_load_primary_module(struct modctl *modp)
18830Sstevel@tonic-gate {
18840Sstevel@tonic-gate 	struct modctl *dep;
18850Sstevel@tonic-gate 	struct module *mp;
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 	if (kobj_load_module(modp, 0) != 0)
18880Sstevel@tonic-gate 		return (-1);
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate 	mp = modp->mod_mp;
18910Sstevel@tonic-gate 	mp->flags |= KOBJ_PRIM;
18920Sstevel@tonic-gate 
18930Sstevel@tonic-gate 	/* Bind new module to its dependents */
18940Sstevel@tonic-gate 	if (mp->depends_on != NULL && (dep =
18950Sstevel@tonic-gate 	    mod_already_loaded(mp->depends_on)) == NULL) {
18960Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
18970Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG) {
18980Sstevel@tonic-gate 			_kobj_printf(ops, "krtld: failed to resolve deps "
18990Sstevel@tonic-gate 			    "for primary %s\n", modp->mod_modname);
19000Sstevel@tonic-gate 		}
19010Sstevel@tonic-gate #endif
19020Sstevel@tonic-gate 		return (-1);
19030Sstevel@tonic-gate 	}
19040Sstevel@tonic-gate 
19050Sstevel@tonic-gate 	add_dependent(mp, dep->mod_mp);
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 	/*
19080Sstevel@tonic-gate 	 * Relocate it.  This module may not be part of a link map, so we
19090Sstevel@tonic-gate 	 * can't use bind_primary.
19100Sstevel@tonic-gate 	 */
19110Sstevel@tonic-gate 	if (do_common(mp) < 0 || do_symbols(mp, 0) < 0 ||
19120Sstevel@tonic-gate 	    do_relocations(mp) < 0) {
19130Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
19140Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG) {
19150Sstevel@tonic-gate 			_kobj_printf(ops, "krtld: failed to relocate "
19160Sstevel@tonic-gate 			    "primary %s\n", modp->mod_modname);
19170Sstevel@tonic-gate 		}
19180Sstevel@tonic-gate #endif
19190Sstevel@tonic-gate 		return (-1);
19200Sstevel@tonic-gate 	}
19210Sstevel@tonic-gate 
19220Sstevel@tonic-gate 	return (0);
19230Sstevel@tonic-gate }
19240Sstevel@tonic-gate 
19250Sstevel@tonic-gate static void
19260Sstevel@tonic-gate module_assign(struct modctl *cp, struct module *mp)
19270Sstevel@tonic-gate {
19280Sstevel@tonic-gate 	if (standalone) {
19290Sstevel@tonic-gate 		cp->mod_mp = mp;
19300Sstevel@tonic-gate 		return;
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 	mutex_enter(&mod_lock);
19330Sstevel@tonic-gate 	cp->mod_mp = mp;
19340Sstevel@tonic-gate 	cp->mod_gencount++;
19350Sstevel@tonic-gate 	mutex_exit(&mod_lock);
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate 
19380Sstevel@tonic-gate void
19390Sstevel@tonic-gate kobj_unload_module(struct modctl *modp)
19400Sstevel@tonic-gate {
19410Sstevel@tonic-gate 	struct module *mp = modp->mod_mp;
19420Sstevel@tonic-gate 
19430Sstevel@tonic-gate 	if ((_moddebug & MODDEBUG_KEEPTEXT) && mp) {
19440Sstevel@tonic-gate 		_kobj_printf(ops, "text for %s ", mp->filename);
19450Sstevel@tonic-gate 		_kobj_printf(ops, "was at %p\n", mp->text);
19460Sstevel@tonic-gate 		mp->text = NULL;	/* don't actually free it */
19470Sstevel@tonic-gate 	}
19480Sstevel@tonic-gate 
19490Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODUNLOADING, modp);
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 	/*
19520Sstevel@tonic-gate 	 * Null out mod_mp first, so consumers (debuggers) know not to look
19530Sstevel@tonic-gate 	 * at the module structure any more.
19540Sstevel@tonic-gate 	 */
19550Sstevel@tonic-gate 	mutex_enter(&mod_lock);
19560Sstevel@tonic-gate 	modp->mod_mp = NULL;
19570Sstevel@tonic-gate 	mutex_exit(&mod_lock);
19580Sstevel@tonic-gate 
19590Sstevel@tonic-gate 	kobj_notify(KOBJ_NOTIFY_MODUNLOADED, modp);
19600Sstevel@tonic-gate 	free_module_data(mp);
19610Sstevel@tonic-gate }
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate static void
19640Sstevel@tonic-gate free_module_data(struct module *mp)
19650Sstevel@tonic-gate {
19660Sstevel@tonic-gate 	struct module_list *lp, *tmp;
19670Sstevel@tonic-gate 	int ksyms_exported = 0;
19680Sstevel@tonic-gate 
19690Sstevel@tonic-gate 	lp = mp->head;
19700Sstevel@tonic-gate 	while (lp) {
19710Sstevel@tonic-gate 		tmp = lp;
19720Sstevel@tonic-gate 		lp = lp->next;
19730Sstevel@tonic-gate 		kobj_free((char *)tmp, sizeof (*tmp));
19740Sstevel@tonic-gate 	}
19750Sstevel@tonic-gate 
19760Sstevel@tonic-gate 	rw_enter(&ksyms_lock, RW_WRITER);
19770Sstevel@tonic-gate 	if (mp->symspace) {
19780Sstevel@tonic-gate 		if (vmem_contains(ksyms_arena, mp->symspace, mp->symsize)) {
19790Sstevel@tonic-gate 			vmem_free(ksyms_arena, mp->symspace, mp->symsize);
19800Sstevel@tonic-gate 			ksyms_exported = 1;
19810Sstevel@tonic-gate 		} else {
19820Sstevel@tonic-gate 			if (mp->flags & KOBJ_NOKSYMS)
19830Sstevel@tonic-gate 				ksyms_exported = 1;
19840Sstevel@tonic-gate 			kobj_free(mp->symspace, mp->symsize);
19850Sstevel@tonic-gate 		}
19860Sstevel@tonic-gate 	}
19870Sstevel@tonic-gate 	rw_exit(&ksyms_lock);
19880Sstevel@tonic-gate 
19890Sstevel@tonic-gate 	if (mp->ctfdata) {
19900Sstevel@tonic-gate 		if (vmem_contains(ctf_arena, mp->ctfdata, mp->ctfsize))
19910Sstevel@tonic-gate 			vmem_free(ctf_arena, mp->ctfdata, mp->ctfsize);
19920Sstevel@tonic-gate 		else
19930Sstevel@tonic-gate 			kobj_free(mp->ctfdata, mp->ctfsize);
19940Sstevel@tonic-gate 	}
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 	if (mp->sigdata)
19970Sstevel@tonic-gate 		kobj_free(mp->sigdata, mp->sigsize);
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate 	/*
20000Sstevel@tonic-gate 	 * We did not get far enough into kobj_export_ksyms() to free allocated
20010Sstevel@tonic-gate 	 * buffers because we encounted error conditions. Free the buffers.
20020Sstevel@tonic-gate 	 */
20030Sstevel@tonic-gate 	if ((ksyms_exported == 0) && (mp->shdrs != NULL)) {
20040Sstevel@tonic-gate 		uint_t shn;
20050Sstevel@tonic-gate 		Shdr *shp;
20060Sstevel@tonic-gate 
20070Sstevel@tonic-gate 		for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
20080Sstevel@tonic-gate 			shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
20090Sstevel@tonic-gate 			switch (shp->sh_type) {
20100Sstevel@tonic-gate 			case SHT_RELA:
20110Sstevel@tonic-gate 			case SHT_REL:
20120Sstevel@tonic-gate 				if (shp->sh_addr != 0)
20130Sstevel@tonic-gate 					kobj_free((void *)shp->sh_addr,
20140Sstevel@tonic-gate 					    shp->sh_size);
20150Sstevel@tonic-gate 				break;
20160Sstevel@tonic-gate 			}
20170Sstevel@tonic-gate 		}
20180Sstevel@tonic-gate err_free_done:
20190Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_PRIM)) {
20200Sstevel@tonic-gate 			kobj_free(mp->shdrs,
20210Sstevel@tonic-gate 			    mp->hdr.e_shentsize * mp->hdr.e_shnum);
20220Sstevel@tonic-gate 		}
20230Sstevel@tonic-gate 	}
20240Sstevel@tonic-gate 
20250Sstevel@tonic-gate 	if (mp->bss)
20260Sstevel@tonic-gate 		vmem_free(data_arena, (void *)mp->bss, mp->bss_size);
20270Sstevel@tonic-gate 
20280Sstevel@tonic-gate 	if (mp->fbt_tab)
20290Sstevel@tonic-gate 		kobj_texthole_free(mp->fbt_tab, mp->fbt_size);
20300Sstevel@tonic-gate 
20310Sstevel@tonic-gate 	if (mp->textwin_base)
20320Sstevel@tonic-gate 		kobj_textwin_free(mp);
20330Sstevel@tonic-gate 
20340Sstevel@tonic-gate 	if (mp->sdt_probes != NULL) {
20350Sstevel@tonic-gate 		sdt_probedesc_t *sdp = mp->sdt_probes, *next;
20360Sstevel@tonic-gate 
20370Sstevel@tonic-gate 		while (sdp != NULL) {
20380Sstevel@tonic-gate 			next = sdp->sdpd_next;
20390Sstevel@tonic-gate 			kobj_free(sdp->sdpd_name, strlen(sdp->sdpd_name) + 1);
20400Sstevel@tonic-gate 			kobj_free(sdp, sizeof (sdt_probedesc_t));
20410Sstevel@tonic-gate 			sdp = next;
20420Sstevel@tonic-gate 		}
20430Sstevel@tonic-gate 	}
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate 	if (mp->sdt_tab)
20460Sstevel@tonic-gate 		kobj_texthole_free(mp->sdt_tab, mp->sdt_size);
20470Sstevel@tonic-gate 	if (mp->text)
20480Sstevel@tonic-gate 		vmem_free(text_arena, mp->text, mp->text_size);
20490Sstevel@tonic-gate 	if (mp->data)
20500Sstevel@tonic-gate 		vmem_free(data_arena, mp->data, mp->data_size);
20510Sstevel@tonic-gate 	if (mp->depends_on)
20520Sstevel@tonic-gate 		kobj_free(mp->depends_on, strlen(mp->depends_on)+1);
20530Sstevel@tonic-gate 	if (mp->filename)
20540Sstevel@tonic-gate 		kobj_free(mp->filename, strlen(mp->filename)+1);
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate 	kobj_free((char *)mp, sizeof (*mp));
20570Sstevel@tonic-gate }
20580Sstevel@tonic-gate 
20590Sstevel@tonic-gate static int
20600Sstevel@tonic-gate get_progbits(struct module *mp, struct _buf *file)
20610Sstevel@tonic-gate {
20620Sstevel@tonic-gate 	struct proginfo *tp, *dp, *sdp;
20630Sstevel@tonic-gate 	Shdr *shp;
20640Sstevel@tonic-gate 	reloc_dest_t dest = NULL;
20650Sstevel@tonic-gate 	uintptr_t bits_ptr;
20660Sstevel@tonic-gate 	uintptr_t text = 0, data, sdata = 0, textptr;
20670Sstevel@tonic-gate 	uint_t shn;
20680Sstevel@tonic-gate 	int err = -1;
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate 	tp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT);
20710Sstevel@tonic-gate 	dp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT);
20720Sstevel@tonic-gate 	sdp = kobj_zalloc(sizeof (struct proginfo), KM_WAIT);
20730Sstevel@tonic-gate 	/*
20740Sstevel@tonic-gate 	 * loop through sections to find out how much space we need
20750Sstevel@tonic-gate 	 * for text, data, (also bss that is already assigned)
20760Sstevel@tonic-gate 	 */
20770Sstevel@tonic-gate 	if (get_progbits_size(mp, tp, dp, sdp) < 0)
20780Sstevel@tonic-gate 		goto done;
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate 	mp->text_size = tp->size;
20810Sstevel@tonic-gate 	mp->data_size = dp->size;
20820Sstevel@tonic-gate 
20830Sstevel@tonic-gate 	if (standalone) {
20840Sstevel@tonic-gate 		mp->text = kobj_segbrk(&_etext, mp->text_size,
20850Sstevel@tonic-gate 			tp->align, _data);
20860Sstevel@tonic-gate 		/*
20870Sstevel@tonic-gate 		 * If we can't grow the text segment, try the
20880Sstevel@tonic-gate 		 * data segment before failing.
20890Sstevel@tonic-gate 		 */
20900Sstevel@tonic-gate 		if (mp->text == NULL) {
20910Sstevel@tonic-gate 			mp->text = kobj_segbrk(&_edata, mp->text_size,
20920Sstevel@tonic-gate 					tp->align, 0);
20930Sstevel@tonic-gate 		}
20940Sstevel@tonic-gate 
20950Sstevel@tonic-gate 		mp->data = kobj_segbrk(&_edata, mp->data_size, dp->align, 0);
20960Sstevel@tonic-gate 
20970Sstevel@tonic-gate 		if (mp->text == NULL || mp->data == NULL)
20980Sstevel@tonic-gate 			goto done;
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate 	} else {
21010Sstevel@tonic-gate 		if (text_arena == NULL)
21020Sstevel@tonic-gate 			kobj_vmem_init(&text_arena, &data_arena);
21030Sstevel@tonic-gate 
21040Sstevel@tonic-gate 		/*
21050Sstevel@tonic-gate 		 * some architectures may want to load the module on a
21060Sstevel@tonic-gate 		 * page that is currently read only. It may not be
21070Sstevel@tonic-gate 		 * possible for those architectures to remap their page
21080Sstevel@tonic-gate 		 * on the fly. So we provide a facility for them to hang
21090Sstevel@tonic-gate 		 * a private hook where the memory they assign the module
21100Sstevel@tonic-gate 		 * is not the actual place where the module loads.
21110Sstevel@tonic-gate 		 *
21120Sstevel@tonic-gate 		 * In this case there are two addresses that deal with the
21130Sstevel@tonic-gate 		 * modload.
21140Sstevel@tonic-gate 		 * 1) the final destination of the module
21150Sstevel@tonic-gate 		 * 2) the address that is used to view the newly
21160Sstevel@tonic-gate 		 * loaded module until all the relocations relative to 1
21170Sstevel@tonic-gate 		 * above are completed.
21180Sstevel@tonic-gate 		 *
21190Sstevel@tonic-gate 		 * That is what dest is used for below.
21200Sstevel@tonic-gate 		 */
21210Sstevel@tonic-gate 		mp->text_size += tp->align;
21220Sstevel@tonic-gate 		mp->data_size += dp->align;
21230Sstevel@tonic-gate 
21240Sstevel@tonic-gate 		mp->text = kobj_text_alloc(text_arena, mp->text_size);
21250Sstevel@tonic-gate 
21260Sstevel@tonic-gate 		/*
21270Sstevel@tonic-gate 		 * a remap is taking place. Align the text ptr relative
21280Sstevel@tonic-gate 		 * to the secondary mapping. That is where the bits will
21290Sstevel@tonic-gate 		 * be read in.
21300Sstevel@tonic-gate 		 */
21310Sstevel@tonic-gate 		if (kvseg.s_base != NULL && !vmem_contains(heaptext_arena,
21320Sstevel@tonic-gate 		    mp->text, mp->text_size)) {
21330Sstevel@tonic-gate 			off_t	off = (uintptr_t)mp->text & PAGEOFFSET;
21340Sstevel@tonic-gate 			size_t	size = P2ROUNDUP(mp->text_size + off, PAGESIZE);
21350Sstevel@tonic-gate 			caddr_t	map = vmem_alloc(heap_arena, size, VM_SLEEP);
21360Sstevel@tonic-gate 			caddr_t orig = mp->text - off;
21370Sstevel@tonic-gate 			pgcnt_t pages = size / PAGESIZE;
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate 			dest = (reloc_dest_t)(map + off);
21400Sstevel@tonic-gate 			text = ALIGN((uintptr_t)dest, tp->align);
21410Sstevel@tonic-gate 
21420Sstevel@tonic-gate 			while (pages--) {
21430Sstevel@tonic-gate 				hat_devload(kas.a_hat, map, PAGESIZE,
21440Sstevel@tonic-gate 				    hat_getpfnum(kas.a_hat, orig),
21450Sstevel@tonic-gate 				    PROT_READ | PROT_WRITE | PROT_EXEC,
21460Sstevel@tonic-gate 				    HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
21470Sstevel@tonic-gate 				map += PAGESIZE;
21480Sstevel@tonic-gate 				orig += PAGESIZE;
21490Sstevel@tonic-gate 			}
21500Sstevel@tonic-gate 			/*
21510Sstevel@tonic-gate 			 * Since we set up a non-cacheable mapping, we need
21520Sstevel@tonic-gate 			 * to flush any old entries in the cache that might
21530Sstevel@tonic-gate 			 * be left around from the read-only mapping.
21540Sstevel@tonic-gate 			 */
21550Sstevel@tonic-gate 			dcache_flushall();
21560Sstevel@tonic-gate 		}
21570Sstevel@tonic-gate 		if (mp->data_size)
21580Sstevel@tonic-gate 			mp->data = vmem_alloc(data_arena, mp->data_size,
21590Sstevel@tonic-gate 			    VM_SLEEP | VM_BESTFIT);
21600Sstevel@tonic-gate 	}
21610Sstevel@tonic-gate 	textptr = (uintptr_t)mp->text;
21620Sstevel@tonic-gate 	textptr = ALIGN(textptr, tp->align);
21630Sstevel@tonic-gate 	mp->destination = dest;
21640Sstevel@tonic-gate 
21650Sstevel@tonic-gate 	/*
21660Sstevel@tonic-gate 	 * This is the case where a remap is not being done.
21670Sstevel@tonic-gate 	 */
21680Sstevel@tonic-gate 	if (text == 0)
21690Sstevel@tonic-gate 		text = ALIGN((uintptr_t)mp->text, tp->align);
21700Sstevel@tonic-gate 	data = ALIGN((uintptr_t)mp->data, dp->align);
21710Sstevel@tonic-gate 
21720Sstevel@tonic-gate 	/* now loop though sections assigning addresses and loading the data */
21730Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
21740Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
21750Sstevel@tonic-gate 		if (!(shp->sh_flags & SHF_ALLOC))
21760Sstevel@tonic-gate 			continue;
21770Sstevel@tonic-gate 
21780Sstevel@tonic-gate 		if ((shp->sh_flags & SHF_WRITE) == 0)
21790Sstevel@tonic-gate 			bits_ptr = text;
21800Sstevel@tonic-gate 		else if (shp->sh_flags & SHF_NEUT_SHORT)
21810Sstevel@tonic-gate 			bits_ptr = sdata;
21820Sstevel@tonic-gate 		else
21830Sstevel@tonic-gate 			bits_ptr = data;
21840Sstevel@tonic-gate 
21850Sstevel@tonic-gate 		bits_ptr = ALIGN(bits_ptr, shp->sh_addralign);
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 		if (shp->sh_type == SHT_NOBITS) {
21880Sstevel@tonic-gate 			/*
21890Sstevel@tonic-gate 			 * Zero bss.
21900Sstevel@tonic-gate 			 */
21910Sstevel@tonic-gate 			bzero((caddr_t)bits_ptr, shp->sh_size);
21920Sstevel@tonic-gate 			shp->sh_type = SHT_PROGBITS;
21930Sstevel@tonic-gate 		} else {
21940Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)bits_ptr,
21950Sstevel@tonic-gate 			    shp->sh_size, shp->sh_offset) < 0)
21960Sstevel@tonic-gate 				goto done;
21970Sstevel@tonic-gate 		}
21980Sstevel@tonic-gate 
21990Sstevel@tonic-gate 		if (shp->sh_flags & SHF_WRITE) {
22000Sstevel@tonic-gate 			shp->sh_addr = bits_ptr;
22010Sstevel@tonic-gate 		} else {
22020Sstevel@tonic-gate 			textptr = ALIGN(textptr, shp->sh_addralign);
22030Sstevel@tonic-gate 			shp->sh_addr = textptr;
22040Sstevel@tonic-gate 			textptr += shp->sh_size;
22050Sstevel@tonic-gate 		}
22060Sstevel@tonic-gate 
22070Sstevel@tonic-gate 		bits_ptr += shp->sh_size;
22080Sstevel@tonic-gate 		if ((shp->sh_flags & SHF_WRITE) == 0)
22090Sstevel@tonic-gate 			text = bits_ptr;
22100Sstevel@tonic-gate 		else if (shp->sh_flags & SHF_NEUT_SHORT)
22110Sstevel@tonic-gate 			sdata = bits_ptr;
22120Sstevel@tonic-gate 		else
22130Sstevel@tonic-gate 			data = bits_ptr;
22140Sstevel@tonic-gate 	}
22150Sstevel@tonic-gate 
22160Sstevel@tonic-gate 	err = 0;
22170Sstevel@tonic-gate done:
22180Sstevel@tonic-gate 	/*
22190Sstevel@tonic-gate 	 * Free and mark as freed the section headers here so that
22200Sstevel@tonic-gate 	 * free_module_data() does not have to worry about this buffer.
22210Sstevel@tonic-gate 	 *
22220Sstevel@tonic-gate 	 * This buffer is freed here because one of the possible reasons
22230Sstevel@tonic-gate 	 * for error is a section with non-zero sh_addr and in that case
22240Sstevel@tonic-gate 	 * free_module_data() would have no way of recognizing that this
22250Sstevel@tonic-gate 	 * buffer was unallocated.
22260Sstevel@tonic-gate 	 */
22270Sstevel@tonic-gate 	if (err != 0) {
22280Sstevel@tonic-gate 		kobj_free(mp->shdrs, mp->hdr.e_shentsize * mp->hdr.e_shnum);
22290Sstevel@tonic-gate 		mp->shdrs = NULL;
22300Sstevel@tonic-gate 	}
22310Sstevel@tonic-gate 
22320Sstevel@tonic-gate 	(void) kobj_free(tp, sizeof (struct proginfo));
22330Sstevel@tonic-gate 	(void) kobj_free(dp, sizeof (struct proginfo));
22340Sstevel@tonic-gate 	(void) kobj_free(sdp, sizeof (struct proginfo));
22350Sstevel@tonic-gate 
22360Sstevel@tonic-gate 	return (err);
22370Sstevel@tonic-gate }
22380Sstevel@tonic-gate 
22390Sstevel@tonic-gate /*
22400Sstevel@tonic-gate  * Go through suppress_sym_list to see if "multiply defined"
22410Sstevel@tonic-gate  * warning of this symbol should be suppressed.  Return 1 if
22420Sstevel@tonic-gate  * warning should be suppressed, 0 otherwise.
22430Sstevel@tonic-gate  */
22440Sstevel@tonic-gate static int
22450Sstevel@tonic-gate kobj_suppress_warning(char *symname)
22460Sstevel@tonic-gate {
22470Sstevel@tonic-gate 	int	i;
22480Sstevel@tonic-gate 
22490Sstevel@tonic-gate 	for (i = 0; suppress_sym_list[i] != NULL; i++) {
22500Sstevel@tonic-gate 		if (strcmp(suppress_sym_list[i], symname) == 0)
22510Sstevel@tonic-gate 			return (1);
22520Sstevel@tonic-gate 	}
22530Sstevel@tonic-gate 
22540Sstevel@tonic-gate 	return (0);
22550Sstevel@tonic-gate }
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate static int
22580Sstevel@tonic-gate get_syms(struct module *mp, struct _buf *file)
22590Sstevel@tonic-gate {
22600Sstevel@tonic-gate 	uint_t		shn;
22610Sstevel@tonic-gate 	Shdr	*shp;
22620Sstevel@tonic-gate 	uint_t		i;
22630Sstevel@tonic-gate 	Sym	*sp, *ksp;
22640Sstevel@tonic-gate 	char		*symname;
22650Sstevel@tonic-gate 	int		dosymtab = 0;
22660Sstevel@tonic-gate 	extern char 	stubs_base[], stubs_end[];
22670Sstevel@tonic-gate 
22680Sstevel@tonic-gate 	/*
22690Sstevel@tonic-gate 	 * Find the interesting sections.
22700Sstevel@tonic-gate 	 */
22710Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
22720Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
22730Sstevel@tonic-gate 		switch (shp->sh_type) {
22740Sstevel@tonic-gate 		case SHT_SYMTAB:
22750Sstevel@tonic-gate 			mp->symtbl_section = shn;
22760Sstevel@tonic-gate 			mp->symhdr = shp;
22770Sstevel@tonic-gate 			dosymtab++;
22780Sstevel@tonic-gate 			break;
22790Sstevel@tonic-gate 
22800Sstevel@tonic-gate 		case SHT_RELA:
22810Sstevel@tonic-gate 		case SHT_REL:
22820Sstevel@tonic-gate 			/*
22830Sstevel@tonic-gate 			 * Already loaded.
22840Sstevel@tonic-gate 			 */
22850Sstevel@tonic-gate 			if (shp->sh_addr)
22860Sstevel@tonic-gate 				continue;
22870Sstevel@tonic-gate 			shp->sh_addr = (Addr)
22880Sstevel@tonic-gate 			    kobj_alloc(shp->sh_size, KM_WAIT|KM_TMP);
22890Sstevel@tonic-gate 
22900Sstevel@tonic-gate 			if (kobj_read_file(file, (char *)shp->sh_addr,
22910Sstevel@tonic-gate 			    shp->sh_size, shp->sh_offset) < 0) {
22920Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_syms: %s, ",
22930Sstevel@tonic-gate 				    mp->filename);
22940Sstevel@tonic-gate 				_kobj_printf(ops, "error reading section %d\n",
22950Sstevel@tonic-gate 				    shn);
22960Sstevel@tonic-gate 				return (-1);
22970Sstevel@tonic-gate 			}
22980Sstevel@tonic-gate 			break;
22990Sstevel@tonic-gate 		}
23000Sstevel@tonic-gate 	}
23010Sstevel@tonic-gate 
23020Sstevel@tonic-gate 	/*
23030Sstevel@tonic-gate 	 * This is true for a stripped executable.  In the case of
23040Sstevel@tonic-gate 	 * 'unix' it can be stripped but it still contains the SHT_DYNSYM,
23050Sstevel@tonic-gate 	 * and since that symbol information is still present everything
23060Sstevel@tonic-gate 	 * is just fine.
23070Sstevel@tonic-gate 	 */
23080Sstevel@tonic-gate 	if (!dosymtab) {
23090Sstevel@tonic-gate 		if (mp->flags & KOBJ_EXEC)
23100Sstevel@tonic-gate 			return (0);
23110Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_syms: %s ",
23120Sstevel@tonic-gate 			mp->filename);
23130Sstevel@tonic-gate 		_kobj_printf(ops, "no SHT_SYMTAB symbol table found\n");
23140Sstevel@tonic-gate 		return (-1);
23150Sstevel@tonic-gate 	}
23160Sstevel@tonic-gate 
23170Sstevel@tonic-gate 	/*
23180Sstevel@tonic-gate 	 * get the associated string table header
23190Sstevel@tonic-gate 	 */
23200Sstevel@tonic-gate 	if ((mp->symhdr == 0) || (mp->symhdr->sh_link >= mp->hdr.e_shnum))
23210Sstevel@tonic-gate 		return (-1);
23220Sstevel@tonic-gate 	mp->strhdr = (Shdr *)
23230Sstevel@tonic-gate 		(mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize);
23240Sstevel@tonic-gate 
23250Sstevel@tonic-gate 	mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize;
23260Sstevel@tonic-gate 	mp->hashsize = kobj_gethashsize(mp->nsyms);
23270Sstevel@tonic-gate 
23280Sstevel@tonic-gate 	/*
23290Sstevel@tonic-gate 	 * Allocate space for the symbol table, buckets, chains, and strings.
23300Sstevel@tonic-gate 	 */
23310Sstevel@tonic-gate 	mp->symsize = mp->symhdr->sh_size +
23320Sstevel@tonic-gate 	    (mp->hashsize + mp->nsyms) * sizeof (symid_t) + mp->strhdr->sh_size;
23330Sstevel@tonic-gate 	mp->symspace = kobj_zalloc(mp->symsize, KM_WAIT|KM_SCRATCH);
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate 	mp->symtbl = mp->symspace;
23360Sstevel@tonic-gate 	mp->buckets = (symid_t *)(mp->symtbl + mp->symhdr->sh_size);
23370Sstevel@tonic-gate 	mp->chains = mp->buckets + mp->hashsize;
23380Sstevel@tonic-gate 	mp->strings = (char *)(mp->chains + mp->nsyms);
23390Sstevel@tonic-gate 
23400Sstevel@tonic-gate 	if (kobj_read_file(file, mp->symtbl,
23410Sstevel@tonic-gate 	    mp->symhdr->sh_size, mp->symhdr->sh_offset) < 0 ||
23420Sstevel@tonic-gate 	    kobj_read_file(file, mp->strings,
23430Sstevel@tonic-gate 	    mp->strhdr->sh_size, mp->strhdr->sh_offset) < 0)
23440Sstevel@tonic-gate 		return (-1);
23450Sstevel@tonic-gate 
23460Sstevel@tonic-gate 	/*
23470Sstevel@tonic-gate 	 * loop through the symbol table adjusting values to account
23480Sstevel@tonic-gate 	 * for where each section got loaded into memory.  Also
23490Sstevel@tonic-gate 	 * fill in the hash table.
23500Sstevel@tonic-gate 	 */
23510Sstevel@tonic-gate 	for (i = 1; i < mp->nsyms; i++) {
23520Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + i * mp->symhdr->sh_entsize);
23530Sstevel@tonic-gate 		if (sp->st_shndx < SHN_LORESERVE) {
23540Sstevel@tonic-gate 			if (sp->st_shndx >= mp->hdr.e_shnum) {
23550Sstevel@tonic-gate 				_kobj_printf(ops, "%s bad shndx ",
23560Sstevel@tonic-gate 				    file->_name);
23570Sstevel@tonic-gate 				_kobj_printf(ops, "in symbol %d\n", i);
23580Sstevel@tonic-gate 				return (-1);
23590Sstevel@tonic-gate 			}
23600Sstevel@tonic-gate 			shp = (Shdr *)
23610Sstevel@tonic-gate 			    (mp->shdrs +
23620Sstevel@tonic-gate 			    sp->st_shndx * mp->hdr.e_shentsize);
23630Sstevel@tonic-gate 			if (!(mp->flags & KOBJ_EXEC))
23640Sstevel@tonic-gate 				sp->st_value += shp->sh_addr;
23650Sstevel@tonic-gate 		}
23660Sstevel@tonic-gate 
23670Sstevel@tonic-gate 		if (sp->st_name == 0 || sp->st_shndx == SHN_UNDEF)
23680Sstevel@tonic-gate 			continue;
23690Sstevel@tonic-gate 		if (sp->st_name >= mp->strhdr->sh_size)
23700Sstevel@tonic-gate 			return (-1);
23710Sstevel@tonic-gate 
23720Sstevel@tonic-gate 		symname = mp->strings + sp->st_name;
23730Sstevel@tonic-gate 
23740Sstevel@tonic-gate 		if (!(mp->flags & KOBJ_EXEC) &&
23750Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) == STB_GLOBAL) {
23760Sstevel@tonic-gate 			ksp = kobj_lookup_all(mp, symname, 0);
23770Sstevel@tonic-gate 
23780Sstevel@tonic-gate 			if (ksp && ELF_ST_BIND(ksp->st_info) == STB_GLOBAL &&
23790Sstevel@tonic-gate 			    !kobj_suppress_warning(symname) &&
23800Sstevel@tonic-gate 			    sp->st_shndx != SHN_UNDEF &&
23810Sstevel@tonic-gate 			    sp->st_shndx != SHN_COMMON &&
23820Sstevel@tonic-gate 			    ksp->st_shndx != SHN_UNDEF &&
23830Sstevel@tonic-gate 			    ksp->st_shndx != SHN_COMMON) {
23840Sstevel@tonic-gate 				/*
23850Sstevel@tonic-gate 				 * Unless this symbol is a stub, it's multiply
23860Sstevel@tonic-gate 				 * defined.  Multiply-defined symbols are
23870Sstevel@tonic-gate 				 * usually bad, but some objects (kmdb) have
23880Sstevel@tonic-gate 				 * a legitimate need to have their own
23890Sstevel@tonic-gate 				 * copies of common functions.
23900Sstevel@tonic-gate 				 */
23910Sstevel@tonic-gate 				if ((standalone ||
23920Sstevel@tonic-gate 				    ksp->st_value < (uintptr_t)stubs_base ||
23930Sstevel@tonic-gate 				    ksp->st_value >= (uintptr_t)stubs_end) &&
23940Sstevel@tonic-gate 				    !(mp->flags & KOBJ_IGNMULDEF)) {
23950Sstevel@tonic-gate 					_kobj_printf(ops,
23960Sstevel@tonic-gate 					    "%s symbol ", file->_name);
23970Sstevel@tonic-gate 					_kobj_printf(ops,
23980Sstevel@tonic-gate 					    "%s multiply defined\n", symname);
23990Sstevel@tonic-gate 				}
24000Sstevel@tonic-gate 			}
24010Sstevel@tonic-gate 		}
24020Sstevel@tonic-gate 		sym_insert(mp, symname, i);
24030Sstevel@tonic-gate 	}
24040Sstevel@tonic-gate 
24050Sstevel@tonic-gate 	return (0);
24060Sstevel@tonic-gate }
24070Sstevel@tonic-gate 
24080Sstevel@tonic-gate static int
24090Sstevel@tonic-gate get_ctf(struct module *mp, struct _buf *file)
24100Sstevel@tonic-gate {
24110Sstevel@tonic-gate 	char *shstrtab, *ctfdata;
24120Sstevel@tonic-gate 	size_t shstrlen;
24130Sstevel@tonic-gate 	Shdr *shp;
24140Sstevel@tonic-gate 	uint_t i;
24150Sstevel@tonic-gate 
24160Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_NOCTF)
24170Sstevel@tonic-gate 		return (0); /* do not attempt to even load CTF data */
24180Sstevel@tonic-gate 
24190Sstevel@tonic-gate 	if (mp->hdr.e_shstrndx >= mp->hdr.e_shnum) {
24200Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_ctf: %s, ",
24210Sstevel@tonic-gate 		    mp->filename);
24220Sstevel@tonic-gate 		_kobj_printf(ops, "corrupt e_shstrndx %u\n",
24230Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
24240Sstevel@tonic-gate 		return (-1);
24250Sstevel@tonic-gate 	}
24260Sstevel@tonic-gate 
24270Sstevel@tonic-gate 	shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize);
24280Sstevel@tonic-gate 	shstrlen = shp->sh_size;
24290Sstevel@tonic-gate 	shstrtab = kobj_alloc(shstrlen, KM_WAIT|KM_TMP);
24300Sstevel@tonic-gate 
24310Sstevel@tonic-gate 	if (kobj_read_file(file, shstrtab, shstrlen, shp->sh_offset) < 0) {
24320Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_ctf: %s, ",
24330Sstevel@tonic-gate 		    mp->filename);
24340Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %u\n",
24350Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
24360Sstevel@tonic-gate 		kobj_free(shstrtab, shstrlen);
24370Sstevel@tonic-gate 		return (-1);
24380Sstevel@tonic-gate 	}
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate 	for (i = 0; i < mp->hdr.e_shnum; i++) {
24410Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + i * mp->hdr.e_shentsize);
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 		if (shp->sh_size != 0 && shp->sh_name < shstrlen &&
24440Sstevel@tonic-gate 		    strcmp(shstrtab + shp->sh_name, ".SUNW_ctf") == 0) {
24450Sstevel@tonic-gate 			ctfdata = kobj_alloc(shp->sh_size, KM_WAIT|KM_SCRATCH);
24460Sstevel@tonic-gate 
24470Sstevel@tonic-gate 			if (kobj_read_file(file, ctfdata, shp->sh_size,
24480Sstevel@tonic-gate 			    shp->sh_offset) < 0) {
24490Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_ctf: %s, error "
24500Sstevel@tonic-gate 				    "reading .SUNW_ctf data\n", mp->filename);
24510Sstevel@tonic-gate 				kobj_free(ctfdata, shp->sh_size);
24520Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
24530Sstevel@tonic-gate 				return (-1);
24540Sstevel@tonic-gate 			}
24550Sstevel@tonic-gate 
24560Sstevel@tonic-gate 			mp->ctfdata = ctfdata;
24570Sstevel@tonic-gate 			mp->ctfsize = shp->sh_size;
24580Sstevel@tonic-gate 			break;
24590Sstevel@tonic-gate 		}
24600Sstevel@tonic-gate 	}
24610Sstevel@tonic-gate 
24620Sstevel@tonic-gate 	kobj_free(shstrtab, shstrlen);
24630Sstevel@tonic-gate 	return (0);
24640Sstevel@tonic-gate }
24650Sstevel@tonic-gate 
24660Sstevel@tonic-gate #define	SHA1_DIGEST_LENGTH	20	/* SHA1 digest length in bytes */
24670Sstevel@tonic-gate 
24680Sstevel@tonic-gate /*
24690Sstevel@tonic-gate  * Return the hash of the ELF sections that are memory resident.
24700Sstevel@tonic-gate  * i.e. text and data.  We skip a SHT_NOBITS section since it occupies
24710Sstevel@tonic-gate  * no space in the file. We use SHA1 here since libelfsign uses
24720Sstevel@tonic-gate  * it and both places need to use the same algorithm.
24730Sstevel@tonic-gate  */
24740Sstevel@tonic-gate static void
24750Sstevel@tonic-gate crypto_es_hash(struct module *mp, char *hash, char *shstrtab)
24760Sstevel@tonic-gate {
24770Sstevel@tonic-gate 	uint_t shn;
24780Sstevel@tonic-gate 	Shdr *shp;
24790Sstevel@tonic-gate 	SHA1_CTX ctx;
24800Sstevel@tonic-gate 
24810Sstevel@tonic-gate 	SHA1Init(&ctx);
24820Sstevel@tonic-gate 
24830Sstevel@tonic-gate 	for (shn = 1; shn < mp->hdr.e_shnum; shn++) {
24840Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
24850Sstevel@tonic-gate 		if (!(shp->sh_flags & SHF_ALLOC) || shp->sh_size == 0)
24860Sstevel@tonic-gate 			continue;
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate 		/*
24890Sstevel@tonic-gate 		 * The check should ideally be shp->sh_type == SHT_NOBITS.
24900Sstevel@tonic-gate 		 * However, we can't do that check here as get_progbits()
24910Sstevel@tonic-gate 		 * resets the type.
24920Sstevel@tonic-gate 		 */
24930Sstevel@tonic-gate 		if (strcmp(shstrtab + shp->sh_name, ".bss") == 0)
24940Sstevel@tonic-gate 			continue;
24950Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
24960Sstevel@tonic-gate 		if (kobj_debug & D_DEBUG)
24970Sstevel@tonic-gate 			_kobj_printf(ops,
24980Sstevel@tonic-gate 			    "krtld: crypto_es_hash: updating hash with"
24990Sstevel@tonic-gate 			    " %s data size=%d\n", shstrtab + shp->sh_name,
25000Sstevel@tonic-gate 				shp->sh_size);
25010Sstevel@tonic-gate #endif
25020Sstevel@tonic-gate 		ASSERT(shp->sh_addr != NULL);
25030Sstevel@tonic-gate 		SHA1Update(&ctx, (const uint8_t *)shp->sh_addr, shp->sh_size);
25040Sstevel@tonic-gate 	}
25050Sstevel@tonic-gate 
25060Sstevel@tonic-gate 	SHA1Final((uchar_t *)hash, &ctx);
25070Sstevel@tonic-gate }
25080Sstevel@tonic-gate 
25090Sstevel@tonic-gate /*
25100Sstevel@tonic-gate  * Get the .SUNW_signature section for the module, it it exists.
25110Sstevel@tonic-gate  *
25120Sstevel@tonic-gate  * This section exists only for crypto modules. None of the
25130Sstevel@tonic-gate  * primary modules have this section currently.
25140Sstevel@tonic-gate  */
25150Sstevel@tonic-gate static void
25160Sstevel@tonic-gate get_signature(struct module *mp, struct _buf *file)
25170Sstevel@tonic-gate {
25180Sstevel@tonic-gate 	char *shstrtab, *sigdata = NULL;
25190Sstevel@tonic-gate 	size_t shstrlen;
25200Sstevel@tonic-gate 	Shdr *shp;
25210Sstevel@tonic-gate 	uint_t i;
25220Sstevel@tonic-gate 
25230Sstevel@tonic-gate 	if (mp->hdr.e_shstrndx >= mp->hdr.e_shnum) {
25240Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_signature: %s, ",
25250Sstevel@tonic-gate 		    mp->filename);
25260Sstevel@tonic-gate 		_kobj_printf(ops, "corrupt e_shstrndx %u\n",
25270Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
25280Sstevel@tonic-gate 		return;
25290Sstevel@tonic-gate 	}
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 	shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize);
25320Sstevel@tonic-gate 	shstrlen = shp->sh_size;
25330Sstevel@tonic-gate 	shstrtab = kobj_alloc(shstrlen, KM_WAIT|KM_TMP);
25340Sstevel@tonic-gate 
25350Sstevel@tonic-gate 	if (kobj_read_file(file, shstrtab, shstrlen, shp->sh_offset) < 0) {
25360Sstevel@tonic-gate 		_kobj_printf(ops, "krtld: get_signature: %s, ",
25370Sstevel@tonic-gate 		    mp->filename);
25380Sstevel@tonic-gate 		_kobj_printf(ops, "error reading section %u\n",
25390Sstevel@tonic-gate 		    mp->hdr.e_shstrndx);
25400Sstevel@tonic-gate 		kobj_free(shstrtab, shstrlen);
25410Sstevel@tonic-gate 		return;
25420Sstevel@tonic-gate 	}
25430Sstevel@tonic-gate 
25440Sstevel@tonic-gate 	for (i = 0; i < mp->hdr.e_shnum; i++) {
25450Sstevel@tonic-gate 		shp = (Shdr *)(mp->shdrs + i * mp->hdr.e_shentsize);
25460Sstevel@tonic-gate 		if (shp->sh_size != 0 && shp->sh_name < shstrlen &&
25470Sstevel@tonic-gate 		    strcmp(shstrtab + shp->sh_name,
25480Sstevel@tonic-gate 		    ELF_SIGNATURE_SECTION) == 0) {
25490Sstevel@tonic-gate 			filesig_vers_t filesig_version;
25500Sstevel@tonic-gate 			size_t sigsize = shp->sh_size + SHA1_DIGEST_LENGTH;
25510Sstevel@tonic-gate 			sigdata = kobj_alloc(sigsize, KM_WAIT|KM_SCRATCH);
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 			if (kobj_read_file(file, sigdata, shp->sh_size,
25540Sstevel@tonic-gate 			    shp->sh_offset) < 0) {
25550Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: get_signature: %s,"
25560Sstevel@tonic-gate 				    " error reading .SUNW_signature data\n",
25570Sstevel@tonic-gate 				    mp->filename);
25580Sstevel@tonic-gate 				kobj_free(sigdata, sigsize);
25590Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
25600Sstevel@tonic-gate 				return;
25610Sstevel@tonic-gate 			}
25620Sstevel@tonic-gate 			filesig_version = ((struct filesignatures *)sigdata)->
25630Sstevel@tonic-gate 			    filesig_sig.filesig_version;
25640Sstevel@tonic-gate 			if (!(filesig_version == FILESIG_VERSION1 ||
25650Sstevel@tonic-gate 			    filesig_version == FILESIG_VERSION3)) {
25660Sstevel@tonic-gate 				/* skip versions we don't understand */
25670Sstevel@tonic-gate 				kobj_free(sigdata, sigsize);
25680Sstevel@tonic-gate 				kobj_free(shstrtab, shstrlen);
25690Sstevel@tonic-gate 				return;
25700Sstevel@tonic-gate 			}
25710Sstevel@tonic-gate 
25720Sstevel@tonic-gate 			mp->sigdata = sigdata;
25730Sstevel@tonic-gate 			mp->sigsize = sigsize;
25740Sstevel@tonic-gate 			break;
25750Sstevel@tonic-gate 		}
25760Sstevel@tonic-gate 	}
25770Sstevel@tonic-gate 
25780Sstevel@tonic-gate 	if (sigdata != NULL) {
25790Sstevel@tonic-gate 		crypto_es_hash(mp, sigdata + shp->sh_size, shstrtab);
25800Sstevel@tonic-gate 	}
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 	kobj_free(shstrtab, shstrlen);
25830Sstevel@tonic-gate }
25840Sstevel@tonic-gate 
25850Sstevel@tonic-gate static void
25860Sstevel@tonic-gate add_dependent(struct module *mp, struct module *dep)
25870Sstevel@tonic-gate {
25880Sstevel@tonic-gate 	struct module_list *lp;
25890Sstevel@tonic-gate 
25900Sstevel@tonic-gate 	for (lp = mp->head; lp; lp = lp->next) {
25910Sstevel@tonic-gate 		if (lp->mp == dep)
25920Sstevel@tonic-gate 			return;	/* already on the list */
25930Sstevel@tonic-gate 	}
25940Sstevel@tonic-gate 
25950Sstevel@tonic-gate 	if (lp == NULL) {
25960Sstevel@tonic-gate 		lp = kobj_zalloc(sizeof (*lp), KM_WAIT);
25970Sstevel@tonic-gate 
25980Sstevel@tonic-gate 		lp->mp = dep;
25990Sstevel@tonic-gate 		lp->next = NULL;
26000Sstevel@tonic-gate 		if (mp->tail)
26010Sstevel@tonic-gate 			mp->tail->next = lp;
26020Sstevel@tonic-gate 		else
26030Sstevel@tonic-gate 			mp->head = lp;
26040Sstevel@tonic-gate 		mp->tail = lp;
26050Sstevel@tonic-gate 	}
26060Sstevel@tonic-gate }
26070Sstevel@tonic-gate 
26080Sstevel@tonic-gate static int
26090Sstevel@tonic-gate do_dependents(struct modctl *modp, char *modname, size_t modnamelen)
26100Sstevel@tonic-gate {
26110Sstevel@tonic-gate 	struct module *mp;
26120Sstevel@tonic-gate 	struct modctl *req;
26130Sstevel@tonic-gate 	char *d, *p, *q;
26140Sstevel@tonic-gate 	int c;
26150Sstevel@tonic-gate 	char *err_modname = NULL;
26160Sstevel@tonic-gate 
26170Sstevel@tonic-gate 	mp = modp->mod_mp;
26180Sstevel@tonic-gate 
26190Sstevel@tonic-gate 	if ((p = mp->depends_on) == NULL)
26200Sstevel@tonic-gate 		return (0);
26210Sstevel@tonic-gate 
26220Sstevel@tonic-gate 	for (;;) {
26230Sstevel@tonic-gate 		/*
26240Sstevel@tonic-gate 		 * Skip space.
26250Sstevel@tonic-gate 		 */
26260Sstevel@tonic-gate 		while (*p && (*p == ' ' || *p == '\t'))
26270Sstevel@tonic-gate 			p++;
26280Sstevel@tonic-gate 		/*
26290Sstevel@tonic-gate 		 * Get module name.
26300Sstevel@tonic-gate 		 */
26310Sstevel@tonic-gate 		d = p;
26320Sstevel@tonic-gate 		q = modname;
26330Sstevel@tonic-gate 		c = 0;
26340Sstevel@tonic-gate 		while (*p && *p != ' ' && *p != '\t') {
26350Sstevel@tonic-gate 			if (c < modnamelen - 1) {
26360Sstevel@tonic-gate 				*q++ = *p;
26370Sstevel@tonic-gate 				c++;
26380Sstevel@tonic-gate 			}
26390Sstevel@tonic-gate 			p++;
26400Sstevel@tonic-gate 		}
26410Sstevel@tonic-gate 
26420Sstevel@tonic-gate 		if (q == modname)
26430Sstevel@tonic-gate 			break;
26440Sstevel@tonic-gate 
26450Sstevel@tonic-gate 		if (c == modnamelen - 1) {
26460Sstevel@tonic-gate 			char *dep = kobj_alloc(p - d + 1, KM_WAIT|KM_TMP);
26470Sstevel@tonic-gate 
26480Sstevel@tonic-gate 			(void) strncpy(dep, d,  p - d + 1);
26490Sstevel@tonic-gate 			dep[p - d] = '\0';
26500Sstevel@tonic-gate 
26510Sstevel@tonic-gate 			_kobj_printf(ops, "%s: dependency ", modp->mod_modname);
26520Sstevel@tonic-gate 			_kobj_printf(ops, "'%s' too long ", dep);
26530Sstevel@tonic-gate 			_kobj_printf(ops, "(max %d chars)\n", modnamelen);
26540Sstevel@tonic-gate 
26550Sstevel@tonic-gate 			kobj_free(dep, p - d + 1);
26560Sstevel@tonic-gate 
26570Sstevel@tonic-gate 			return (-1);
26580Sstevel@tonic-gate 		}
26590Sstevel@tonic-gate 
26600Sstevel@tonic-gate 		*q = '\0';
26610Sstevel@tonic-gate 		if ((req = mod_load_requisite(modp, modname)) == NULL) {
26620Sstevel@tonic-gate #ifndef	KOBJ_DEBUG
26630Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_LOADMSG) {
26640Sstevel@tonic-gate #endif	/* KOBJ_DEBUG */
26650Sstevel@tonic-gate 				_kobj_printf(ops,
26660Sstevel@tonic-gate 				    "%s: unable to resolve dependency, ",
26670Sstevel@tonic-gate 				    modp->mod_modname);
26680Sstevel@tonic-gate 				_kobj_printf(ops, "cannot load module '%s'\n",
26690Sstevel@tonic-gate 				    modname);
26700Sstevel@tonic-gate #ifndef	KOBJ_DEBUG
26710Sstevel@tonic-gate 			}
26720Sstevel@tonic-gate #endif	/* KOBJ_DEBUG */
26730Sstevel@tonic-gate 			if (err_modname == NULL) {
26740Sstevel@tonic-gate 				/*
26750Sstevel@tonic-gate 				 * This must be the same size as the modname
26760Sstevel@tonic-gate 				 * one.
26770Sstevel@tonic-gate 				 */
26780Sstevel@tonic-gate 				err_modname = kobj_zalloc(MODMAXNAMELEN,
26790Sstevel@tonic-gate 				    KM_WAIT);
26800Sstevel@tonic-gate 
26810Sstevel@tonic-gate 				/*
26820Sstevel@tonic-gate 				 * We can use strcpy() here without fearing
26830Sstevel@tonic-gate 				 * the NULL terminator because the size of
26840Sstevel@tonic-gate 				 * err_modname is the same as one of modname,
26850Sstevel@tonic-gate 				 * and it's filled with zeros.
26860Sstevel@tonic-gate 				 */
26870Sstevel@tonic-gate 				(void) strcpy(err_modname, modname);
26880Sstevel@tonic-gate 			}
26890Sstevel@tonic-gate 			continue;
26900Sstevel@tonic-gate 		}
26910Sstevel@tonic-gate 
26920Sstevel@tonic-gate 		add_dependent(mp, req->mod_mp);
26930Sstevel@tonic-gate 		mod_release_mod(req);
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate 	}
26960Sstevel@tonic-gate 
26970Sstevel@tonic-gate 	if (err_modname != NULL) {
26980Sstevel@tonic-gate 		/*
26990Sstevel@tonic-gate 		 * Copy the first module name where you detect an error to keep
27000Sstevel@tonic-gate 		 * its behavior the same as before.
27010Sstevel@tonic-gate 		 * This way keeps minimizing the memory use for error
27020Sstevel@tonic-gate 		 * modules, and this might be important at boot time because
27030Sstevel@tonic-gate 		 * the memory usage is a crucial factor for booting in most
27040Sstevel@tonic-gate 		 * cases. You can expect more verbose messages when using
27050Sstevel@tonic-gate 		 * a debug kernel or setting a bit in moddebug.
27060Sstevel@tonic-gate 		 */
27070Sstevel@tonic-gate 		bzero(modname, MODMAXNAMELEN);
27080Sstevel@tonic-gate 		(void) strcpy(modname, err_modname);
27090Sstevel@tonic-gate 		kobj_free(err_modname, MODMAXNAMELEN);
27100Sstevel@tonic-gate 		return (-1);
27110Sstevel@tonic-gate 	}
27120Sstevel@tonic-gate 
27130Sstevel@tonic-gate 	return (0);
27140Sstevel@tonic-gate }
27150Sstevel@tonic-gate 
27160Sstevel@tonic-gate static int
27170Sstevel@tonic-gate do_common(struct module *mp)
27180Sstevel@tonic-gate {
27190Sstevel@tonic-gate 	int err;
27200Sstevel@tonic-gate 
27210Sstevel@tonic-gate 	/*
27220Sstevel@tonic-gate 	 * first time through, assign all symbols defined in other
27230Sstevel@tonic-gate 	 * modules, and count up how much common space will be needed
27240Sstevel@tonic-gate 	 * (bss_size and bss_align)
27250Sstevel@tonic-gate 	 */
27260Sstevel@tonic-gate 	if ((err = do_symbols(mp, 0)) < 0)
27270Sstevel@tonic-gate 		return (err);
27280Sstevel@tonic-gate 	/*
27290Sstevel@tonic-gate 	 * increase bss_size by the maximum delta that could be
27300Sstevel@tonic-gate 	 * computed by the ALIGN below
27310Sstevel@tonic-gate 	 */
27320Sstevel@tonic-gate 	mp->bss_size += mp->bss_align;
27330Sstevel@tonic-gate 	if (mp->bss_size) {
27340Sstevel@tonic-gate 		if (standalone)
27350Sstevel@tonic-gate 			mp->bss = (uintptr_t)kobj_segbrk(&_edata, mp->bss_size,
27360Sstevel@tonic-gate 			    MINALIGN, 0);
27370Sstevel@tonic-gate 		else
27380Sstevel@tonic-gate 			mp->bss = (uintptr_t)vmem_alloc(data_arena,
27390Sstevel@tonic-gate 			    mp->bss_size, VM_SLEEP | VM_BESTFIT);
27400Sstevel@tonic-gate 		bzero((void *)mp->bss, mp->bss_size);
27410Sstevel@tonic-gate 		/* now assign addresses to all common symbols */
27420Sstevel@tonic-gate 		if ((err = do_symbols(mp, ALIGN(mp->bss, mp->bss_align))) < 0)
27430Sstevel@tonic-gate 			return (err);
27440Sstevel@tonic-gate 	}
27450Sstevel@tonic-gate 	return (0);
27460Sstevel@tonic-gate }
27470Sstevel@tonic-gate 
27480Sstevel@tonic-gate static int
27490Sstevel@tonic-gate do_symbols(struct module *mp, Elf64_Addr bss_base)
27500Sstevel@tonic-gate {
27510Sstevel@tonic-gate 	int bss_align;
27520Sstevel@tonic-gate 	uintptr_t bss_ptr;
27530Sstevel@tonic-gate 	int err;
27540Sstevel@tonic-gate 	int i;
27550Sstevel@tonic-gate 	Sym *sp, *sp1;
27560Sstevel@tonic-gate 	char *name;
27570Sstevel@tonic-gate 	int assign;
27580Sstevel@tonic-gate 	int resolved = 1;
27590Sstevel@tonic-gate 
27600Sstevel@tonic-gate 	/*
27610Sstevel@tonic-gate 	 * Nothing left to do (optimization).
27620Sstevel@tonic-gate 	 */
27630Sstevel@tonic-gate 	if (mp->flags & KOBJ_RESOLVED)
27640Sstevel@tonic-gate 		return (0);
27650Sstevel@tonic-gate 
27660Sstevel@tonic-gate 	assign = (bss_base) ? 1 : 0;
27670Sstevel@tonic-gate 	bss_ptr = bss_base;
27680Sstevel@tonic-gate 	bss_align = 0;
27690Sstevel@tonic-gate 	err = 0;
27700Sstevel@tonic-gate 
27710Sstevel@tonic-gate 	for (i = 1; i < mp->nsyms; i++) {
27720Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + mp->symhdr->sh_entsize * i);
27730Sstevel@tonic-gate 		/*
27740Sstevel@tonic-gate 		 * we know that st_name is in bounds, since get_sections
27750Sstevel@tonic-gate 		 * has already checked all of the symbols
27760Sstevel@tonic-gate 		 */
27770Sstevel@tonic-gate 		name = mp->strings + sp->st_name;
27780Sstevel@tonic-gate 		if (sp->st_shndx != SHN_UNDEF && sp->st_shndx != SHN_COMMON)
27790Sstevel@tonic-gate 			continue;
27800Sstevel@tonic-gate #ifdef	__sparc
27810Sstevel@tonic-gate 		/*
27820Sstevel@tonic-gate 		 * Register symbols are ignored in the kernel
27830Sstevel@tonic-gate 		 */
27840Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_SPARC_REGISTER) {
27850Sstevel@tonic-gate 			if (*name != '\0') {
27860Sstevel@tonic-gate 				_kobj_printf(ops, "%s: named REGISTER symbol ",
27870Sstevel@tonic-gate 						mp->filename);
27880Sstevel@tonic-gate 				_kobj_printf(ops, "not supported '%s'\n",
27890Sstevel@tonic-gate 						name);
27900Sstevel@tonic-gate 				err = DOSYM_UNDEF;
27910Sstevel@tonic-gate 			}
27920Sstevel@tonic-gate 			continue;
27930Sstevel@tonic-gate 		}
27940Sstevel@tonic-gate #endif	/* __sparc */
27950Sstevel@tonic-gate 		/*
27960Sstevel@tonic-gate 		 * TLS symbols are ignored in the kernel
27970Sstevel@tonic-gate 		 */
27980Sstevel@tonic-gate 		if (ELF_ST_TYPE(sp->st_info) == STT_TLS) {
27990Sstevel@tonic-gate 			_kobj_printf(ops, "%s: TLS symbol ",
28000Sstevel@tonic-gate 					mp->filename);
28010Sstevel@tonic-gate 			_kobj_printf(ops, "not supported '%s'\n",
28020Sstevel@tonic-gate 					name);
28030Sstevel@tonic-gate 			err = DOSYM_UNDEF;
28040Sstevel@tonic-gate 			continue;
28050Sstevel@tonic-gate 		}
28060Sstevel@tonic-gate 
28070Sstevel@tonic-gate 		if (ELF_ST_BIND(sp->st_info) != STB_LOCAL) {
28080Sstevel@tonic-gate 			if ((sp1 = kobj_lookup_all(mp, name, 0)) != NULL) {
28090Sstevel@tonic-gate 				sp->st_shndx = SHN_ABS;
28100Sstevel@tonic-gate 				sp->st_value = sp1->st_value;
28110Sstevel@tonic-gate 				continue;
28120Sstevel@tonic-gate 			}
28130Sstevel@tonic-gate 		}
28140Sstevel@tonic-gate 
28150Sstevel@tonic-gate 		if (sp->st_shndx == SHN_UNDEF) {
28160Sstevel@tonic-gate 			resolved = 0;
28170Sstevel@tonic-gate 
28180Sstevel@tonic-gate 			if (strncmp(name, sdt_prefix, strlen(sdt_prefix)) == 0)
28190Sstevel@tonic-gate 				continue;
28200Sstevel@tonic-gate 
28210Sstevel@tonic-gate 			/*
28220Sstevel@tonic-gate 			 * If it's not a weak reference and it's
28230Sstevel@tonic-gate 			 * not a primary object, it's an error.
28240Sstevel@tonic-gate 			 * (Primary objects may take more than
28250Sstevel@tonic-gate 			 * one pass to resolve)
28260Sstevel@tonic-gate 			 */
28270Sstevel@tonic-gate 			if (!(mp->flags & KOBJ_PRIM) &&
28280Sstevel@tonic-gate 			    ELF_ST_BIND(sp->st_info) != STB_WEAK) {
28290Sstevel@tonic-gate 				_kobj_printf(ops, "%s: undefined symbol",
28300Sstevel@tonic-gate 				    mp->filename);
28310Sstevel@tonic-gate 				_kobj_printf(ops, " '%s'\n", name);
28320Sstevel@tonic-gate 				/*
28330Sstevel@tonic-gate 				 * Try to determine whether this symbol
28340Sstevel@tonic-gate 				 * represents a dependency on obsolete
28350Sstevel@tonic-gate 				 * unsafe driver support.  This is just
28360Sstevel@tonic-gate 				 * to make the warning more informative.
28370Sstevel@tonic-gate 				 */
28380Sstevel@tonic-gate 				if (strcmp(name, "sleep") == 0 ||
28390Sstevel@tonic-gate 				    strcmp(name, "unsleep") == 0 ||
28400Sstevel@tonic-gate 				    strcmp(name, "wakeup") == 0 ||
28410Sstevel@tonic-gate 				    strcmp(name, "bsd_compat_ioctl") == 0 ||
28420Sstevel@tonic-gate 				    strcmp(name, "unsafe_driver") == 0 ||
28430Sstevel@tonic-gate 				    strncmp(name, "spl", 3) == 0 ||
28440Sstevel@tonic-gate 				    strncmp(name, "i_ddi_spl", 9) == 0)
28450Sstevel@tonic-gate 					err = DOSYM_UNSAFE;
28460Sstevel@tonic-gate 				if (err == 0)
28470Sstevel@tonic-gate 					err = DOSYM_UNDEF;
28480Sstevel@tonic-gate 			}
28490Sstevel@tonic-gate 			continue;
28500Sstevel@tonic-gate 		}
28510Sstevel@tonic-gate 		/*
28520Sstevel@tonic-gate 		 * It's a common symbol - st_value is the
28530Sstevel@tonic-gate 		 * required alignment.
28540Sstevel@tonic-gate 		 */
28550Sstevel@tonic-gate 		if (sp->st_value > bss_align)
28560Sstevel@tonic-gate 			bss_align = sp->st_value;
28570Sstevel@tonic-gate 		bss_ptr = ALIGN(bss_ptr, sp->st_value);
28580Sstevel@tonic-gate 		if (assign) {
28590Sstevel@tonic-gate 			sp->st_shndx = SHN_ABS;
28600Sstevel@tonic-gate 			sp->st_value = bss_ptr;
28610Sstevel@tonic-gate 		}
28620Sstevel@tonic-gate 		bss_ptr += sp->st_size;
28630Sstevel@tonic-gate 	}
28640Sstevel@tonic-gate 	if (err)
28650Sstevel@tonic-gate 		return (err);
28660Sstevel@tonic-gate 	if (assign == 0 && mp->bss == NULL) {
28670Sstevel@tonic-gate 		mp->bss_align = bss_align;
28680Sstevel@tonic-gate 		mp->bss_size = bss_ptr;
28690Sstevel@tonic-gate 	} else if (resolved) {
28700Sstevel@tonic-gate 		mp->flags |= KOBJ_RESOLVED;
28710Sstevel@tonic-gate 	}
28720Sstevel@tonic-gate 
28730Sstevel@tonic-gate 	return (0);
28740Sstevel@tonic-gate }
28750Sstevel@tonic-gate 
28760Sstevel@tonic-gate uint_t
28770Sstevel@tonic-gate kobj_hash_name(const char *p)
28780Sstevel@tonic-gate {
28790Sstevel@tonic-gate 	unsigned int g;
28800Sstevel@tonic-gate 	uint_t hval;
28810Sstevel@tonic-gate 
28820Sstevel@tonic-gate 	hval = 0;
28830Sstevel@tonic-gate 	while (*p) {
28840Sstevel@tonic-gate 		hval = (hval << 4) + *p++;
28850Sstevel@tonic-gate 		if ((g = (hval & 0xf0000000)) != 0)
28860Sstevel@tonic-gate 			hval ^= g >> 24;
28870Sstevel@tonic-gate 		hval &= ~g;
28880Sstevel@tonic-gate 	}
28890Sstevel@tonic-gate 	return (hval);
28900Sstevel@tonic-gate }
28910Sstevel@tonic-gate 
28920Sstevel@tonic-gate /* look for name in all modules */
28930Sstevel@tonic-gate uintptr_t
28940Sstevel@tonic-gate kobj_getsymvalue(char *name, int kernelonly)
28950Sstevel@tonic-gate {
28960Sstevel@tonic-gate 	Sym		*sp;
28970Sstevel@tonic-gate 	struct modctl	*modp;
28980Sstevel@tonic-gate 	struct module	*mp;
28990Sstevel@tonic-gate 	uintptr_t	value = 0;
29000Sstevel@tonic-gate 
29010Sstevel@tonic-gate 	if ((sp = kobj_lookup_kernel(name)) != NULL)
29020Sstevel@tonic-gate 		return ((uintptr_t)sp->st_value);
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate 	if (kernelonly)
29050Sstevel@tonic-gate 		return (0);	/* didn't find it in the kernel so give up */
29060Sstevel@tonic-gate 
29070Sstevel@tonic-gate 	mutex_enter(&mod_lock);
29080Sstevel@tonic-gate 	modp = &modules;
29090Sstevel@tonic-gate 	do {
29100Sstevel@tonic-gate 		mp = (struct module *)modp->mod_mp;
29110Sstevel@tonic-gate 		if (mp && !(mp->flags & KOBJ_PRIM) && modp->mod_loaded &&
29120Sstevel@tonic-gate 		    (sp = lookup_one(mp, name))) {
29130Sstevel@tonic-gate 			value = (uintptr_t)sp->st_value;
29140Sstevel@tonic-gate 			break;
29150Sstevel@tonic-gate 		}
29160Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
29170Sstevel@tonic-gate 	mutex_exit(&mod_lock);
29180Sstevel@tonic-gate 	return (value);
29190Sstevel@tonic-gate }
29200Sstevel@tonic-gate 
29210Sstevel@tonic-gate /* look for a symbol near value. */
29220Sstevel@tonic-gate char *
29230Sstevel@tonic-gate kobj_getsymname(uintptr_t value, ulong_t *offset)
29240Sstevel@tonic-gate {
29250Sstevel@tonic-gate 	char *name = NULL;
29260Sstevel@tonic-gate 	struct modctl *modp;
29270Sstevel@tonic-gate 
29280Sstevel@tonic-gate 	struct modctl_list *lp;
29290Sstevel@tonic-gate 	struct module *mp;
29300Sstevel@tonic-gate 
29310Sstevel@tonic-gate 	/*
29320Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
29330Sstevel@tonic-gate 	 */
29340Sstevel@tonic-gate 	for (lp = kobj_lm_lookup(KOBJ_LM_PRIMARY); lp; lp = lp->modl_next) {
29350Sstevel@tonic-gate 		mp = mod(lp);
29360Sstevel@tonic-gate 
29370Sstevel@tonic-gate 		if ((name = kobj_searchsym(mp, value, offset)) != NULL)
29380Sstevel@tonic-gate 			return (name);
29390Sstevel@tonic-gate 	}
29400Sstevel@tonic-gate 
29410Sstevel@tonic-gate 	mutex_enter(&mod_lock);
29420Sstevel@tonic-gate 	modp = &modules;
29430Sstevel@tonic-gate 	do {
29440Sstevel@tonic-gate 		mp = (struct module *)modp->mod_mp;
29450Sstevel@tonic-gate 		if (mp && !(mp->flags & KOBJ_PRIM) && modp->mod_loaded &&
29460Sstevel@tonic-gate 		    (name = kobj_searchsym(mp, value, offset)))
29470Sstevel@tonic-gate 			break;
29480Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
29490Sstevel@tonic-gate 	mutex_exit(&mod_lock);
29500Sstevel@tonic-gate 	return (name);
29510Sstevel@tonic-gate }
29520Sstevel@tonic-gate 
29530Sstevel@tonic-gate /* return address of symbol and size */
29540Sstevel@tonic-gate 
29550Sstevel@tonic-gate uintptr_t
29560Sstevel@tonic-gate kobj_getelfsym(char *name, void *mp, int *size)
29570Sstevel@tonic-gate {
29580Sstevel@tonic-gate 	Sym *sp;
29590Sstevel@tonic-gate 
29600Sstevel@tonic-gate 	if (mp == NULL)
29610Sstevel@tonic-gate 		sp = kobj_lookup_kernel(name);
29620Sstevel@tonic-gate 	else
29630Sstevel@tonic-gate 		sp = lookup_one(mp, name);
29640Sstevel@tonic-gate 
29650Sstevel@tonic-gate 	if (sp == NULL)
29660Sstevel@tonic-gate 		return (0);
29670Sstevel@tonic-gate 
29680Sstevel@tonic-gate 	*size = (int)sp->st_size;
29690Sstevel@tonic-gate 	return ((uintptr_t)sp->st_value);
29700Sstevel@tonic-gate }
29710Sstevel@tonic-gate 
29720Sstevel@tonic-gate uintptr_t
29730Sstevel@tonic-gate kobj_lookup(void *mod, char *name)
29740Sstevel@tonic-gate {
29750Sstevel@tonic-gate 	Sym *sp;
29760Sstevel@tonic-gate 
29770Sstevel@tonic-gate 	sp = lookup_one(mod, name);
29780Sstevel@tonic-gate 
29790Sstevel@tonic-gate 	if (sp == NULL)
29800Sstevel@tonic-gate 		return (0);
29810Sstevel@tonic-gate 
29820Sstevel@tonic-gate 	return ((uintptr_t)sp->st_value);
29830Sstevel@tonic-gate }
29840Sstevel@tonic-gate 
29850Sstevel@tonic-gate char *
29860Sstevel@tonic-gate kobj_searchsym(struct module *mp, uintptr_t value, ulong_t *offset)
29870Sstevel@tonic-gate {
29880Sstevel@tonic-gate 	Sym *symtabptr;
29890Sstevel@tonic-gate 	char *strtabptr;
29900Sstevel@tonic-gate 	int symnum;
29910Sstevel@tonic-gate 	Sym *sym;
29920Sstevel@tonic-gate 	Sym *cursym;
29930Sstevel@tonic-gate 	uintptr_t curval;
29940Sstevel@tonic-gate 
29950Sstevel@tonic-gate 	*offset = (ulong_t)-1l;		/* assume not found */
29960Sstevel@tonic-gate 	cursym  = NULL;
29970Sstevel@tonic-gate 
29980Sstevel@tonic-gate 	if (kobj_addrcheck(mp, (void *)value) != 0)
29990Sstevel@tonic-gate 		return (NULL);		/* not in this module */
30000Sstevel@tonic-gate 
30010Sstevel@tonic-gate 	strtabptr  = mp->strings;
30020Sstevel@tonic-gate 	symtabptr  = (Sym *)mp->symtbl;
30030Sstevel@tonic-gate 
30040Sstevel@tonic-gate 	/*
30050Sstevel@tonic-gate 	 * Scan the module's symbol table for a symbol <= value
30060Sstevel@tonic-gate 	 */
30070Sstevel@tonic-gate 	for (symnum = 1, sym = symtabptr + 1;
30080Sstevel@tonic-gate 	    symnum < mp->nsyms; symnum++, sym = (Sym *)
30090Sstevel@tonic-gate 	    ((uintptr_t)sym + mp->symhdr->sh_entsize)) {
30100Sstevel@tonic-gate 		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) {
30110Sstevel@tonic-gate 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
30120Sstevel@tonic-gate 				continue;
30130Sstevel@tonic-gate 			if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
30140Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info) != STT_FUNC)
30150Sstevel@tonic-gate 				continue;
30160Sstevel@tonic-gate 		}
30170Sstevel@tonic-gate 
30180Sstevel@tonic-gate 		curval = (uintptr_t)sym->st_value;
30190Sstevel@tonic-gate 
30200Sstevel@tonic-gate 		if (curval > value)
30210Sstevel@tonic-gate 			continue;
30220Sstevel@tonic-gate 
30230Sstevel@tonic-gate 		/*
30240Sstevel@tonic-gate 		 * If one or both are functions...
30250Sstevel@tonic-gate 		 */
30260Sstevel@tonic-gate 		if (ELF_ST_TYPE(sym->st_info) == STT_FUNC || (cursym != NULL &&
30270Sstevel@tonic-gate 		    ELF_ST_TYPE(cursym->st_info) == STT_FUNC)) {
30280Sstevel@tonic-gate 			/* Ignore if the address is out of the bounds */
30290Sstevel@tonic-gate 			if (value - sym->st_value >= sym->st_size)
30300Sstevel@tonic-gate 				continue;
30310Sstevel@tonic-gate 
30320Sstevel@tonic-gate 			if (cursym != NULL &&
30330Sstevel@tonic-gate 			    ELF_ST_TYPE(cursym->st_info) == STT_FUNC) {
30340Sstevel@tonic-gate 				/* Prefer the function to the non-function */
30350Sstevel@tonic-gate 				if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
30360Sstevel@tonic-gate 					continue;
30370Sstevel@tonic-gate 
30380Sstevel@tonic-gate 				/* Prefer the larger of the two functions */
30390Sstevel@tonic-gate 				if (sym->st_size <= cursym->st_size)
30400Sstevel@tonic-gate 					continue;
30410Sstevel@tonic-gate 			}
30420Sstevel@tonic-gate 		} else if (value - curval >= *offset) {
30430Sstevel@tonic-gate 			continue;
30440Sstevel@tonic-gate 		}
30450Sstevel@tonic-gate 
30460Sstevel@tonic-gate 		*offset = (ulong_t)(value - curval);
30470Sstevel@tonic-gate 		cursym = sym;
30480Sstevel@tonic-gate 	}
30490Sstevel@tonic-gate 	if (cursym == NULL)
30500Sstevel@tonic-gate 		return (NULL);
30510Sstevel@tonic-gate 
30520Sstevel@tonic-gate 	return (strtabptr + cursym->st_name);
30530Sstevel@tonic-gate }
30540Sstevel@tonic-gate 
30550Sstevel@tonic-gate Sym *
30560Sstevel@tonic-gate kobj_lookup_all(struct module *mp, char *name, int include_self)
30570Sstevel@tonic-gate {
30580Sstevel@tonic-gate 	Sym *sp;
30590Sstevel@tonic-gate 	struct module_list *mlp;
30600Sstevel@tonic-gate 	struct modctl_list *clp;
30610Sstevel@tonic-gate 	struct module *mmp;
30620Sstevel@tonic-gate 
30630Sstevel@tonic-gate 	if (include_self && (sp = lookup_one(mp, name)) != NULL)
30640Sstevel@tonic-gate 		return (sp);
30650Sstevel@tonic-gate 
30660Sstevel@tonic-gate 	for (mlp = mp->head; mlp; mlp = mlp->next) {
30670Sstevel@tonic-gate 		if ((sp = lookup_one(mlp->mp, name)) != NULL &&
30680Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) != STB_LOCAL)
30690Sstevel@tonic-gate 			return (sp);
30700Sstevel@tonic-gate 	}
30710Sstevel@tonic-gate 
30720Sstevel@tonic-gate 	/*
30730Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
30740Sstevel@tonic-gate 	 */
30750Sstevel@tonic-gate 	for (clp = kobj_lm_lookup(KOBJ_LM_PRIMARY); clp; clp = clp->modl_next) {
30760Sstevel@tonic-gate 		mmp = mod(clp);
30770Sstevel@tonic-gate 
30780Sstevel@tonic-gate 		if (mmp == NULL || mp == mmp)
30790Sstevel@tonic-gate 			continue;
30800Sstevel@tonic-gate 
30810Sstevel@tonic-gate 		if ((sp = lookup_one(mmp, name)) != NULL &&
30820Sstevel@tonic-gate 		    ELF_ST_BIND(sp->st_info) != STB_LOCAL)
30830Sstevel@tonic-gate 			return (sp);
30840Sstevel@tonic-gate 	}
30850Sstevel@tonic-gate 	return (NULL);
30860Sstevel@tonic-gate }
30870Sstevel@tonic-gate 
30880Sstevel@tonic-gate Sym *
30890Sstevel@tonic-gate kobj_lookup_kernel(const char *name)
30900Sstevel@tonic-gate {
30910Sstevel@tonic-gate 	struct modctl_list *lp;
30920Sstevel@tonic-gate 	struct module *mp;
30930Sstevel@tonic-gate 	Sym *sp;
30940Sstevel@tonic-gate 
30950Sstevel@tonic-gate 	/*
30960Sstevel@tonic-gate 	 * Loop through the primary kernel modules.
30970Sstevel@tonic-gate 	 */
30980Sstevel@tonic-gate 	for (lp = kobj_lm_lookup(KOBJ_LM_PRIMARY); lp; lp = lp->modl_next) {
30990Sstevel@tonic-gate 		mp = mod(lp);
31000Sstevel@tonic-gate 
31010Sstevel@tonic-gate 		if (mp == NULL)
31020Sstevel@tonic-gate 			continue;
31030Sstevel@tonic-gate 
31040Sstevel@tonic-gate 		if ((sp = lookup_one(mp, name)) != NULL)
31050Sstevel@tonic-gate 			return (sp);
31060Sstevel@tonic-gate 	}
31070Sstevel@tonic-gate 	return (NULL);
31080Sstevel@tonic-gate }
31090Sstevel@tonic-gate 
31100Sstevel@tonic-gate static Sym *
31110Sstevel@tonic-gate lookup_one(struct module *mp, const char *name)
31120Sstevel@tonic-gate {
31130Sstevel@tonic-gate 	symid_t *ip;
31140Sstevel@tonic-gate 	char *name1;
31150Sstevel@tonic-gate 	Sym *sp;
31160Sstevel@tonic-gate 
31170Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
31180Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
31190Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl +
31200Sstevel@tonic-gate 		    mp->symhdr->sh_entsize * *ip);
31210Sstevel@tonic-gate 		name1 = mp->strings + sp->st_name;
31220Sstevel@tonic-gate 		if (strcmp(name, name1) == 0 &&
31230Sstevel@tonic-gate 		    ELF_ST_TYPE(sp->st_info) != STT_FILE &&
31240Sstevel@tonic-gate 		    sp->st_shndx != SHN_UNDEF &&
31250Sstevel@tonic-gate 		    sp->st_shndx != SHN_COMMON)
31260Sstevel@tonic-gate 			return (sp);
31270Sstevel@tonic-gate 	}
31280Sstevel@tonic-gate 	return (NULL);
31290Sstevel@tonic-gate }
31300Sstevel@tonic-gate 
31310Sstevel@tonic-gate /*
31320Sstevel@tonic-gate  * Lookup a given symbol pointer in the module's symbol hash.  If the symbol
31330Sstevel@tonic-gate  * is hashed, return the symbol pointer; otherwise return NULL.
31340Sstevel@tonic-gate  */
31350Sstevel@tonic-gate static Sym *
31360Sstevel@tonic-gate sym_lookup(struct module *mp, Sym *ksp)
31370Sstevel@tonic-gate {
31380Sstevel@tonic-gate 	char *name = mp->strings + ksp->st_name;
31390Sstevel@tonic-gate 	symid_t *ip;
31400Sstevel@tonic-gate 	Sym *sp;
31410Sstevel@tonic-gate 
31420Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
31430Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
31440Sstevel@tonic-gate 		sp = (Sym *)(mp->symtbl + mp->symhdr->sh_entsize * *ip);
31450Sstevel@tonic-gate 		if (sp == ksp)
31460Sstevel@tonic-gate 			return (ksp);
31470Sstevel@tonic-gate 	}
31480Sstevel@tonic-gate 	return (NULL);
31490Sstevel@tonic-gate }
31500Sstevel@tonic-gate 
31510Sstevel@tonic-gate static void
31520Sstevel@tonic-gate sym_insert(struct module *mp, char *name, symid_t index)
31530Sstevel@tonic-gate {
31540Sstevel@tonic-gate 	symid_t *ip;
31550Sstevel@tonic-gate 
31560Sstevel@tonic-gate #ifdef KOBJ_DEBUG
31570Sstevel@tonic-gate 		if (kobj_debug & D_SYMBOLS) {
31580Sstevel@tonic-gate 			static struct module *lastmp = NULL;
31590Sstevel@tonic-gate 			Sym *sp;
31600Sstevel@tonic-gate 			if (lastmp != mp) {
31610Sstevel@tonic-gate 				_kobj_printf(ops,
31620Sstevel@tonic-gate 				    "krtld: symbol entry: file=%s\n",
31630Sstevel@tonic-gate 				    mp->filename);
31640Sstevel@tonic-gate 				_kobj_printf(ops,
31650Sstevel@tonic-gate 				    "krtld:\tsymndx\tvalue\t\t"
31660Sstevel@tonic-gate 				    "symbol name\n");
31670Sstevel@tonic-gate 				lastmp = mp;
31680Sstevel@tonic-gate 			}
31690Sstevel@tonic-gate 			sp = (Sym *)(mp->symtbl +
31700Sstevel@tonic-gate 				index * mp->symhdr->sh_entsize);
31710Sstevel@tonic-gate 			_kobj_printf(ops, "krtld:\t[%3d]", index);
31720Sstevel@tonic-gate 			_kobj_printf(ops, "\t0x%lx", sp->st_value);
31730Sstevel@tonic-gate 			_kobj_printf(ops, "\t%s\n", name);
31740Sstevel@tonic-gate 		}
31750Sstevel@tonic-gate 
31760Sstevel@tonic-gate #endif
31770Sstevel@tonic-gate 	for (ip = &mp->buckets[kobj_hash_name(name) % mp->hashsize]; *ip;
31780Sstevel@tonic-gate 	    ip = &mp->chains[*ip]) {
31790Sstevel@tonic-gate 		;
31800Sstevel@tonic-gate 	}
31810Sstevel@tonic-gate 	*ip = index;
31820Sstevel@tonic-gate }
31830Sstevel@tonic-gate 
31840Sstevel@tonic-gate struct modctl *
31850Sstevel@tonic-gate kobj_boot_mod_lookup(const char *modname)
31860Sstevel@tonic-gate {
31870Sstevel@tonic-gate 	struct modctl *mctl = kobj_modules;
31880Sstevel@tonic-gate 
31890Sstevel@tonic-gate 	do {
31900Sstevel@tonic-gate 		if (strcmp(modname, mctl->mod_modname) == 0)
31910Sstevel@tonic-gate 			return (mctl);
31920Sstevel@tonic-gate 	} while ((mctl = mctl->mod_next) != kobj_modules);
31930Sstevel@tonic-gate 
31940Sstevel@tonic-gate 	return (NULL);
31950Sstevel@tonic-gate }
31960Sstevel@tonic-gate 
31970Sstevel@tonic-gate /*
3198*309Scth  * Determine if the module exists.
3199*309Scth  */
3200*309Scth int
3201*309Scth kobj_path_exists(char *name, int use_path)
3202*309Scth {
3203*309Scth 	struct _buf *file;
3204*309Scth 
3205*309Scth 	file = kobj_open_path(name, use_path, 1);
3206*309Scth #ifdef	MODDIR_SUFFIX
3207*309Scth 	if (file == (struct _buf *)-1)
3208*309Scth 		file = kobj_open_path(name, use_path, 0);
3209*309Scth #endif	/* MODDIR_SUFFIX */
3210*309Scth 	if (file == (struct _buf *)-1)
3211*309Scth 		return (0);
3212*309Scth 	kobj_close_file(file);
3213*309Scth 	return (1);
3214*309Scth }
3215*309Scth 
3216*309Scth /*
32170Sstevel@tonic-gate  * fullname is dynamically allocated to be able to hold the
32180Sstevel@tonic-gate  * maximum size string that can be constructed from name.
32190Sstevel@tonic-gate  * path is exactly like the shell PATH variable.
32200Sstevel@tonic-gate  */
32210Sstevel@tonic-gate struct _buf *
32220Sstevel@tonic-gate kobj_open_path(char *name, int use_path, int use_moddir_suffix)
32230Sstevel@tonic-gate {
32240Sstevel@tonic-gate 	char *p, *q;
32250Sstevel@tonic-gate 	char *pathp;
32260Sstevel@tonic-gate 	char *pathpsave;
32270Sstevel@tonic-gate 	char *fullname;
32280Sstevel@tonic-gate 	int maxpathlen;
32290Sstevel@tonic-gate 	struct _buf *file;
32300Sstevel@tonic-gate 
32310Sstevel@tonic-gate #if !defined(MODDIR_SUFFIX)
32320Sstevel@tonic-gate 	use_moddir_suffix = B_FALSE;
32330Sstevel@tonic-gate #endif
32340Sstevel@tonic-gate 
32350Sstevel@tonic-gate 	if (!use_path)
32360Sstevel@tonic-gate 		pathp = "";		/* use name as specified */
32370Sstevel@tonic-gate 	else
32380Sstevel@tonic-gate 		pathp = module_path;	/* use configured default path */
32390Sstevel@tonic-gate 
32400Sstevel@tonic-gate 	pathpsave = pathp;		/* keep this for error reporting */
32410Sstevel@tonic-gate 
32420Sstevel@tonic-gate 	/*
32430Sstevel@tonic-gate 	 * Allocate enough space for the largest possible fullname.
32440Sstevel@tonic-gate 	 * since path is of the form <directory> : <directory> : ...
32450Sstevel@tonic-gate 	 * we're potentially allocating a little more than we need to
32460Sstevel@tonic-gate 	 * but we'll allocate the exact amount when we find the right directory.
32470Sstevel@tonic-gate 	 * (The + 3 below is one for NULL terminator and one for the '/'
32480Sstevel@tonic-gate 	 * we might have to add at the beginning of path and one for
32490Sstevel@tonic-gate 	 * the '/' between path and name.)
32500Sstevel@tonic-gate 	 */
32510Sstevel@tonic-gate 	maxpathlen = strlen(pathp) + strlen(name) + 3;
32520Sstevel@tonic-gate 	/* sizeof includes null */
32530Sstevel@tonic-gate 	maxpathlen += sizeof (slash_moddir_suffix_slash) - 1;
32540Sstevel@tonic-gate 	fullname = kobj_zalloc(maxpathlen, KM_WAIT);
32550Sstevel@tonic-gate 
32560Sstevel@tonic-gate 	for (;;) {
32570Sstevel@tonic-gate 		p = fullname;
32580Sstevel@tonic-gate 		if (*pathp != '\0' && *pathp != '/')
32590Sstevel@tonic-gate 			*p++ = '/';	/* path must start with '/' */
32600Sstevel@tonic-gate 		while (*pathp && *pathp != ':' && *pathp != ' ')
32610Sstevel@tonic-gate 			*p++ = *pathp++;
32620Sstevel@tonic-gate 		if (p != fullname && p[-1] != '/')
32630Sstevel@tonic-gate 			*p++ = '/';
32640Sstevel@tonic-gate 		if (use_moddir_suffix) {
32650Sstevel@tonic-gate 			char *b = basename(name);
32660Sstevel@tonic-gate 			char *s;
32670Sstevel@tonic-gate 
32680Sstevel@tonic-gate 			/* copy everything up to the base name */
32690Sstevel@tonic-gate 			q = name;
32700Sstevel@tonic-gate 			while (q != b && *q)
32710Sstevel@tonic-gate 				*p++ = *q++;
32720Sstevel@tonic-gate 			s = slash_moddir_suffix_slash;
32730Sstevel@tonic-gate 			while (*s)
32740Sstevel@tonic-gate 				*p++ = *s++;
32750Sstevel@tonic-gate 			/* copy the rest */
32760Sstevel@tonic-gate 			while (*b)
32770Sstevel@tonic-gate 				*p++ = *b++;
32780Sstevel@tonic-gate 		} else {
32790Sstevel@tonic-gate 			q = name;
32800Sstevel@tonic-gate 			while (*q)
32810Sstevel@tonic-gate 				*p++ = *q++;
32820Sstevel@tonic-gate 		}
32830Sstevel@tonic-gate 		*p = 0;
32840Sstevel@tonic-gate 		if ((file = kobj_open_file(fullname)) != (struct _buf *)-1) {
32850Sstevel@tonic-gate 			kobj_free(fullname, maxpathlen);
32860Sstevel@tonic-gate 			return (file);
32870Sstevel@tonic-gate 		}
32880Sstevel@tonic-gate 		if (*pathp == 0)
32890Sstevel@tonic-gate 			break;
32900Sstevel@tonic-gate 		pathp++;
32910Sstevel@tonic-gate 	}
32920Sstevel@tonic-gate 	kobj_free(fullname, maxpathlen);
32930Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG) {
32940Sstevel@tonic-gate 		_kobj_printf(ops, "can't open %s,", name);
32950Sstevel@tonic-gate 		_kobj_printf(ops, " path is %s\n", pathpsave);
32960Sstevel@tonic-gate 	}
32970Sstevel@tonic-gate 	return ((struct _buf *)-1);
32980Sstevel@tonic-gate }
32990Sstevel@tonic-gate 
33000Sstevel@tonic-gate intptr_t
33010Sstevel@tonic-gate kobj_open(char *filename)
33020Sstevel@tonic-gate {
33030Sstevel@tonic-gate 	struct vnode *vp;
33040Sstevel@tonic-gate 	int fd;
33050Sstevel@tonic-gate 
33060Sstevel@tonic-gate 	if (_modrootloaded) {
33070Sstevel@tonic-gate 		struct kobjopen_tctl *ltp = kobjopen_alloc(filename);
33080Sstevel@tonic-gate 		int Errno;
33090Sstevel@tonic-gate 
33100Sstevel@tonic-gate 		/*
33110Sstevel@tonic-gate 		 * Hand off the open to a thread who has a
33120Sstevel@tonic-gate 		 * stack size capable handling the request.
33130Sstevel@tonic-gate 		 */
33140Sstevel@tonic-gate 		if (curthread != &t0) {
33150Sstevel@tonic-gate 			(void) thread_create(NULL, DEFAULTSTKSZ * 2,
33160Sstevel@tonic-gate 			    kobjopen_thread, ltp, 0, &p0, TS_RUN, maxclsyspri);
33170Sstevel@tonic-gate 			sema_p(&ltp->sema);
33180Sstevel@tonic-gate 			Errno = ltp->Errno;
33190Sstevel@tonic-gate 			vp = ltp->vp;
33200Sstevel@tonic-gate 		} else {
33210Sstevel@tonic-gate 			/*
33220Sstevel@tonic-gate 			 * 1098067: module creds should not be those of the
33230Sstevel@tonic-gate 			 * caller
33240Sstevel@tonic-gate 			 */
33250Sstevel@tonic-gate 			cred_t *saved_cred = curthread->t_cred;
33260Sstevel@tonic-gate 			curthread->t_cred = kcred;
33270Sstevel@tonic-gate 			Errno = vn_open(filename, UIO_SYSSPACE, FREAD, 0, &vp,
33280Sstevel@tonic-gate 			    0, 0);
33290Sstevel@tonic-gate 			curthread->t_cred = saved_cred;
33300Sstevel@tonic-gate 		}
33310Sstevel@tonic-gate 		kobjopen_free(ltp);
33320Sstevel@tonic-gate 
33330Sstevel@tonic-gate 		if (Errno) {
33340Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
33350Sstevel@tonic-gate 				_kobj_printf(ops,
33360Sstevel@tonic-gate 				    "kobj_open: vn_open of %s fails, ",
33370Sstevel@tonic-gate 				    filename);
33380Sstevel@tonic-gate 				_kobj_printf(ops, "Errno = %d\n", Errno);
33390Sstevel@tonic-gate 			}
33400Sstevel@tonic-gate 			return (-1);
33410Sstevel@tonic-gate 		} else {
33420Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
33430Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_open: '%s'", filename);
33440Sstevel@tonic-gate 				_kobj_printf(ops, " vp = %p\n", vp);
33450Sstevel@tonic-gate 			}
33460Sstevel@tonic-gate 			return ((intptr_t)vp);
33470Sstevel@tonic-gate 		}
33480Sstevel@tonic-gate 	} else {
33490Sstevel@tonic-gate 		fd = kobj_boot_open(filename, 0);
33500Sstevel@tonic-gate 
33510Sstevel@tonic-gate 		if (_moddebug & MODDEBUG_ERRMSG) {
33520Sstevel@tonic-gate 			if (fd < 0)
33530Sstevel@tonic-gate 				_kobj_printf(ops,
33540Sstevel@tonic-gate 				    "kobj_open: can't open %s\n", filename);
33550Sstevel@tonic-gate 			else {
33560Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_open: '%s'", filename);
33570Sstevel@tonic-gate 				_kobj_printf(ops, " descr = 0x%x\n", fd);
33580Sstevel@tonic-gate 			}
33590Sstevel@tonic-gate 		}
33600Sstevel@tonic-gate 		return ((intptr_t)fd);
33610Sstevel@tonic-gate 	}
33620Sstevel@tonic-gate }
33630Sstevel@tonic-gate 
33640Sstevel@tonic-gate /*
33650Sstevel@tonic-gate  * Calls to kobj_open() are handled off to this routine as a separate thread.
33660Sstevel@tonic-gate  */
33670Sstevel@tonic-gate static void
33680Sstevel@tonic-gate kobjopen_thread(struct kobjopen_tctl *ltp)
33690Sstevel@tonic-gate {
33700Sstevel@tonic-gate 	kmutex_t	cpr_lk;
33710Sstevel@tonic-gate 	callb_cpr_t	cpr_i;
33720Sstevel@tonic-gate 
33730Sstevel@tonic-gate 	mutex_init(&cpr_lk, NULL, MUTEX_DEFAULT, NULL);
33740Sstevel@tonic-gate 	CALLB_CPR_INIT(&cpr_i, &cpr_lk, callb_generic_cpr, "kobjopen");
33750Sstevel@tonic-gate 	ltp->Errno = vn_open(ltp->name, UIO_SYSSPACE, FREAD, 0, &(ltp->vp),
33760Sstevel@tonic-gate 									0, 0);
33770Sstevel@tonic-gate 	sema_v(&ltp->sema);
33780Sstevel@tonic-gate 	mutex_enter(&cpr_lk);
33790Sstevel@tonic-gate 	CALLB_CPR_EXIT(&cpr_i);
33800Sstevel@tonic-gate 	mutex_destroy(&cpr_lk);
33810Sstevel@tonic-gate 	thread_exit();
33820Sstevel@tonic-gate }
33830Sstevel@tonic-gate 
33840Sstevel@tonic-gate /*
33850Sstevel@tonic-gate  * allocate and initialize a kobjopen thread structure
33860Sstevel@tonic-gate  */
33870Sstevel@tonic-gate static struct kobjopen_tctl *
33880Sstevel@tonic-gate kobjopen_alloc(char *filename)
33890Sstevel@tonic-gate {
33900Sstevel@tonic-gate 	struct kobjopen_tctl *ltp = kmem_zalloc(sizeof (*ltp), KM_SLEEP);
33910Sstevel@tonic-gate 
33920Sstevel@tonic-gate 	ASSERT(filename != NULL);
33930Sstevel@tonic-gate 
33940Sstevel@tonic-gate 	ltp->name = kmem_alloc(strlen(filename) + 1, KM_SLEEP);
33950Sstevel@tonic-gate 	bcopy(filename, ltp->name, strlen(filename) + 1);
33960Sstevel@tonic-gate 	sema_init(&ltp->sema, 0, NULL, SEMA_DEFAULT, NULL);
33970Sstevel@tonic-gate 	return (ltp);
33980Sstevel@tonic-gate }
33990Sstevel@tonic-gate 
34000Sstevel@tonic-gate /*
34010Sstevel@tonic-gate  * free a kobjopen thread control structure
34020Sstevel@tonic-gate  */
34030Sstevel@tonic-gate static void
34040Sstevel@tonic-gate kobjopen_free(struct kobjopen_tctl *ltp)
34050Sstevel@tonic-gate {
34060Sstevel@tonic-gate 	sema_destroy(&ltp->sema);
34070Sstevel@tonic-gate 	kmem_free(ltp->name, strlen(ltp->name) + 1);
34080Sstevel@tonic-gate 	kmem_free(ltp, sizeof (*ltp));
34090Sstevel@tonic-gate }
34100Sstevel@tonic-gate 
34110Sstevel@tonic-gate int
34120Sstevel@tonic-gate kobj_read(intptr_t descr, char *buf, unsigned size, unsigned offset)
34130Sstevel@tonic-gate {
34140Sstevel@tonic-gate 	int stat;
34150Sstevel@tonic-gate 	ssize_t resid;
34160Sstevel@tonic-gate 
34170Sstevel@tonic-gate 	if (_modrootloaded) {
34180Sstevel@tonic-gate 		if ((stat = vn_rdwr(UIO_READ, (struct vnode *)descr, buf, size,
34190Sstevel@tonic-gate 		    (offset_t)offset, UIO_SYSSPACE, 0, (rlim64_t)0, CRED(),
34200Sstevel@tonic-gate 		    &resid)) != 0) {
34210Sstevel@tonic-gate 			_kobj_printf(ops,
34220Sstevel@tonic-gate 			    "vn_rdwr failed with error 0x%x\n", stat);
34230Sstevel@tonic-gate 			return (-1);
34240Sstevel@tonic-gate 		}
34250Sstevel@tonic-gate 		return (size - resid);
34260Sstevel@tonic-gate 	} else {
34270Sstevel@tonic-gate 		int count = 0;
34280Sstevel@tonic-gate 
34290Sstevel@tonic-gate 		if (kobj_boot_seek((int)descr, (off_t)0, offset) != 0) {
34300Sstevel@tonic-gate 			_kobj_printf(ops,
34310Sstevel@tonic-gate 			    "kobj_read: seek 0x%x failed\n", offset);
34320Sstevel@tonic-gate 			return (-1);
34330Sstevel@tonic-gate 		}
34340Sstevel@tonic-gate 
34350Sstevel@tonic-gate 		count = kobj_boot_read((int)descr, buf, size);
34360Sstevel@tonic-gate 		if (count < size) {
34370Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG) {
34380Sstevel@tonic-gate 				_kobj_printf(ops,
34390Sstevel@tonic-gate 				    "kobj_read: req %d bytes, ", size);
34400Sstevel@tonic-gate 				_kobj_printf(ops, "got %d\n", count);
34410Sstevel@tonic-gate 			}
34420Sstevel@tonic-gate 		}
34430Sstevel@tonic-gate 		return (count);
34440Sstevel@tonic-gate 	}
34450Sstevel@tonic-gate }
34460Sstevel@tonic-gate 
34470Sstevel@tonic-gate void
34480Sstevel@tonic-gate kobj_close(intptr_t descr)
34490Sstevel@tonic-gate {
34500Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG)
34510Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_close: 0x%lx\n", descr);
34520Sstevel@tonic-gate 
34530Sstevel@tonic-gate 	if (_modrootloaded) {
34540Sstevel@tonic-gate 		struct vnode *vp = (struct vnode *)descr;
34550Sstevel@tonic-gate 		(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED());
34560Sstevel@tonic-gate 		VN_RELE(vp);
34570Sstevel@tonic-gate 	} else
34580Sstevel@tonic-gate 		(void) kobj_boot_close((int)descr);
34590Sstevel@tonic-gate }
34600Sstevel@tonic-gate 
34610Sstevel@tonic-gate struct _buf *
34620Sstevel@tonic-gate kobj_open_file(char *name)
34630Sstevel@tonic-gate {
34640Sstevel@tonic-gate 	struct _buf *file;
34650Sstevel@tonic-gate 	intptr_t fd;
34660Sstevel@tonic-gate 
34670Sstevel@tonic-gate 	if ((fd = kobj_open(name)) == -1) {
34680Sstevel@tonic-gate 		return ((struct _buf *)-1);
34690Sstevel@tonic-gate 	}
34700Sstevel@tonic-gate 
34710Sstevel@tonic-gate 	file = kobj_zalloc(sizeof (struct _buf), KM_WAIT|KM_TMP);
34720Sstevel@tonic-gate 	file->_fd = fd;
34730Sstevel@tonic-gate 	file->_name = kobj_alloc(strlen(name)+1, KM_WAIT|KM_TMP);
34740Sstevel@tonic-gate 	file->_base = kobj_zalloc(MAXBSIZE, KM_WAIT|KM_TMP);
34750Sstevel@tonic-gate 	file->_cnt = file->_size = file->_off = 0;
34760Sstevel@tonic-gate 	file->_ln = 1;
34770Sstevel@tonic-gate 	file->_ptr = file->_base;
34780Sstevel@tonic-gate 	(void) strcpy(file->_name, name);
34790Sstevel@tonic-gate 	return (file);
34800Sstevel@tonic-gate }
34810Sstevel@tonic-gate 
34820Sstevel@tonic-gate void
34830Sstevel@tonic-gate kobj_close_file(struct _buf *file)
34840Sstevel@tonic-gate {
34850Sstevel@tonic-gate 	kobj_close(file->_fd);
34860Sstevel@tonic-gate 	kobj_free(file->_base, MAXBSIZE);
34870Sstevel@tonic-gate 	kobj_free(file->_name, strlen(file->_name)+1);
34880Sstevel@tonic-gate 	kobj_free(file, sizeof (struct _buf));
34890Sstevel@tonic-gate }
34900Sstevel@tonic-gate 
34910Sstevel@tonic-gate int
34920Sstevel@tonic-gate kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
34930Sstevel@tonic-gate {
34940Sstevel@tonic-gate 	int b_size, c_size;
34950Sstevel@tonic-gate 	int b_off;	/* Offset into buffer for start of bcopy */
34960Sstevel@tonic-gate 	int count = 0;
34970Sstevel@tonic-gate 	int page_addr;
34980Sstevel@tonic-gate 
34990Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG) {
35000Sstevel@tonic-gate 		_kobj_printf(ops, "kobj_read_file: size=%x,", size);
35010Sstevel@tonic-gate 		_kobj_printf(ops, " offset=%x at", off);
35020Sstevel@tonic-gate 		_kobj_printf(ops, " buf=%x\n", buf);
35030Sstevel@tonic-gate 	}
35040Sstevel@tonic-gate 
35050Sstevel@tonic-gate 	while (size) {
35060Sstevel@tonic-gate 		page_addr = F_PAGE(off);
35070Sstevel@tonic-gate 		b_size = file->_size;
35080Sstevel@tonic-gate 		/*
35090Sstevel@tonic-gate 		 * If we have the filesystem page the caller's referring to
35100Sstevel@tonic-gate 		 * and we have something in the buffer,
35110Sstevel@tonic-gate 		 * satisfy as much of the request from the buffer as we can.
35120Sstevel@tonic-gate 		 */
35130Sstevel@tonic-gate 		if (page_addr == file->_off && b_size > 0) {
35140Sstevel@tonic-gate 			b_off = B_OFFSET(off);
35150Sstevel@tonic-gate 			c_size = b_size - b_off;
35160Sstevel@tonic-gate 			/*
35170Sstevel@tonic-gate 			 * If there's nothing to copy, we're at EOF.
35180Sstevel@tonic-gate 			 */
35190Sstevel@tonic-gate 			if (c_size <= 0)
35200Sstevel@tonic-gate 				break;
35210Sstevel@tonic-gate 			if (c_size > size)
35220Sstevel@tonic-gate 				c_size = size;
35230Sstevel@tonic-gate 			if (buf) {
35240Sstevel@tonic-gate 				if (_moddebug & MODDEBUG_ERRMSG)
35250Sstevel@tonic-gate 					_kobj_printf(ops, "copying %x bytes\n",
35260Sstevel@tonic-gate 					    c_size);
35270Sstevel@tonic-gate 				bcopy(file->_base+b_off, buf, c_size);
35280Sstevel@tonic-gate 				size -= c_size;
35290Sstevel@tonic-gate 				off += c_size;
35300Sstevel@tonic-gate 				buf += c_size;
35310Sstevel@tonic-gate 				count += c_size;
35320Sstevel@tonic-gate 			} else {
35330Sstevel@tonic-gate 				_kobj_printf(ops, "kobj_read: system error");
35340Sstevel@tonic-gate 				count = -1;
35350Sstevel@tonic-gate 				break;
35360Sstevel@tonic-gate 			}
35370Sstevel@tonic-gate 		} else {
35380Sstevel@tonic-gate 			/*
35390Sstevel@tonic-gate 			 * If the caller's offset is page aligned and
35400Sstevel@tonic-gate 			 * the caller want's at least a filesystem page and
35410Sstevel@tonic-gate 			 * the caller provided a buffer,
35420Sstevel@tonic-gate 			 * read directly into the caller's buffer.
35430Sstevel@tonic-gate 			 */
35440Sstevel@tonic-gate 			if (page_addr == off &&
35450Sstevel@tonic-gate 			    (c_size = F_PAGE(size)) && buf) {
35460Sstevel@tonic-gate 				c_size = kobj_read(file->_fd, buf, c_size,
35470Sstevel@tonic-gate 					page_addr);
35480Sstevel@tonic-gate 				if (c_size < 0) {
35490Sstevel@tonic-gate 					count = -1;
35500Sstevel@tonic-gate 					break;
35510Sstevel@tonic-gate 				}
35520Sstevel@tonic-gate 				count += c_size;
35530Sstevel@tonic-gate 				if (c_size != F_PAGE(size))
35540Sstevel@tonic-gate 					break;
35550Sstevel@tonic-gate 				size -= c_size;
35560Sstevel@tonic-gate 				off += c_size;
35570Sstevel@tonic-gate 				buf += c_size;
35580Sstevel@tonic-gate 			/*
35590Sstevel@tonic-gate 			 * Otherwise, read into our buffer and copy next time
35600Sstevel@tonic-gate 			 * around the loop.
35610Sstevel@tonic-gate 			 */
35620Sstevel@tonic-gate 			} else {
35630Sstevel@tonic-gate 				file->_off = page_addr;
35640Sstevel@tonic-gate 				c_size = kobj_read(file->_fd, file->_base,
35650Sstevel@tonic-gate 						MAXBSIZE, page_addr);
35660Sstevel@tonic-gate 				file->_ptr = file->_base;
35670Sstevel@tonic-gate 				file->_cnt = c_size;
35680Sstevel@tonic-gate 				file->_size = c_size;
35690Sstevel@tonic-gate 				/*
35700Sstevel@tonic-gate 				 * If a _filbuf call or nothing read, break.
35710Sstevel@tonic-gate 				 */
35720Sstevel@tonic-gate 				if (buf == NULL || c_size <= 0) {
35730Sstevel@tonic-gate 					count = c_size;
35740Sstevel@tonic-gate 					break;
35750Sstevel@tonic-gate 				}
35760Sstevel@tonic-gate 			}
35770Sstevel@tonic-gate 			if (_moddebug & MODDEBUG_ERRMSG)
35780Sstevel@tonic-gate 				_kobj_printf(ops, "read %x bytes\n", c_size);
35790Sstevel@tonic-gate 		}
35800Sstevel@tonic-gate 	}
35810Sstevel@tonic-gate 	if (_moddebug & MODDEBUG_ERRMSG)
35820Sstevel@tonic-gate 		_kobj_printf(ops, "count = %x\n", count);
35830Sstevel@tonic-gate 
35840Sstevel@tonic-gate 	return (count);
35850Sstevel@tonic-gate }
35860Sstevel@tonic-gate 
35870Sstevel@tonic-gate int
35880Sstevel@tonic-gate kobj_filbuf(struct _buf *f)
35890Sstevel@tonic-gate {
35900Sstevel@tonic-gate 	if (kobj_read_file(f, NULL, MAXBSIZE, f->_off + f->_size) > 0)
35910Sstevel@tonic-gate 		return (kobj_getc(f));
35920Sstevel@tonic-gate 	return (-1);
35930Sstevel@tonic-gate }
35940Sstevel@tonic-gate 
35950Sstevel@tonic-gate void
35960Sstevel@tonic-gate kobj_free(void *address, size_t size)
35970Sstevel@tonic-gate {
35980Sstevel@tonic-gate 	if (standalone)
35990Sstevel@tonic-gate 		return;
36000Sstevel@tonic-gate 
36010Sstevel@tonic-gate 	kmem_free(address, size);
36020Sstevel@tonic-gate 	kobj_stat.nfree_calls++;
36030Sstevel@tonic-gate 	kobj_stat.nfree += size;
36040Sstevel@tonic-gate }
36050Sstevel@tonic-gate 
36060Sstevel@tonic-gate void *
36070Sstevel@tonic-gate kobj_zalloc(size_t size, int flag)
36080Sstevel@tonic-gate {
36090Sstevel@tonic-gate 	void *v;
36100Sstevel@tonic-gate 
36110Sstevel@tonic-gate 	if ((v = kobj_alloc(size, flag)) != 0) {
36120Sstevel@tonic-gate 		bzero(v, size);
36130Sstevel@tonic-gate 	}
36140Sstevel@tonic-gate 
36150Sstevel@tonic-gate 	return (v);
36160Sstevel@tonic-gate }
36170Sstevel@tonic-gate 
36180Sstevel@tonic-gate void *
36190Sstevel@tonic-gate kobj_alloc(size_t size, int flag)
36200Sstevel@tonic-gate {
36210Sstevel@tonic-gate 	/*
36220Sstevel@tonic-gate 	 * If we are running standalone in the
36230Sstevel@tonic-gate 	 * linker, we ask boot for memory.
36240Sstevel@tonic-gate 	 * Either it's temporary memory that we lose
36250Sstevel@tonic-gate 	 * once boot is mapped out or we allocate it
36260Sstevel@tonic-gate 	 * permanently using the dynamic data segment.
36270Sstevel@tonic-gate 	 */
36280Sstevel@tonic-gate 	if (standalone) {
36290Sstevel@tonic-gate #ifdef __sparc
36300Sstevel@tonic-gate 		if (flag & KM_TMP) {
36310Sstevel@tonic-gate 			return (kobj_tmp_alloc(size));
36320Sstevel@tonic-gate 		} else if (flag & KM_SCRATCH) {
36330Sstevel@tonic-gate 			void *buf = kobj_bs_alloc(size);
36340Sstevel@tonic-gate 
36350Sstevel@tonic-gate 			if (buf != NULL)
36360Sstevel@tonic-gate 				return (buf);
36370Sstevel@tonic-gate #ifdef	KOBJ_DEBUG
36380Sstevel@tonic-gate 			if (kobj_debug & D_DEBUG) {
36390Sstevel@tonic-gate 				_kobj_printf(ops, "krtld: failed scratch alloc "
36400Sstevel@tonic-gate 				    "of %u bytes -- falling back\n", size);
36410Sstevel@tonic-gate 			}
36420Sstevel@tonic-gate #endif
36430Sstevel@tonic-gate 		}
36440Sstevel@tonic-gate 
36450Sstevel@tonic-gate #else /* x86 */
36460Sstevel@tonic-gate 		if (flag & (KM_TMP | KM_SCRATCH))
36470Sstevel@tonic-gate 			return (BOP_ALLOC(ops, 0, size, MINALIGN));
36480Sstevel@tonic-gate #endif
36490Sstevel@tonic-gate 		return (kobj_segbrk(&_edata, size, MINALIGN, 0));
36500Sstevel@tonic-gate 	}
36510Sstevel@tonic-gate 
36520Sstevel@tonic-gate 	kobj_stat.nalloc_calls++;
36530Sstevel@tonic-gate 	kobj_stat.nalloc += size;
36540Sstevel@tonic-gate 
36550Sstevel@tonic-gate 	return (kmem_alloc(size, (flag & KM_NOWAIT) ? KM_NOSLEEP : KM_SLEEP));
36560Sstevel@tonic-gate }
36570Sstevel@tonic-gate 
36580Sstevel@tonic-gate /*
36590Sstevel@tonic-gate  * Allow the "mod" system to sync up with the work
36600Sstevel@tonic-gate  * already done by kobj during the initial loading
36610Sstevel@tonic-gate  * of the kernel.  This also gives us a chance
36620Sstevel@tonic-gate  * to reallocate memory that belongs to boot.
36630Sstevel@tonic-gate  */
36640Sstevel@tonic-gate void
36650Sstevel@tonic-gate kobj_sync(void)
36660Sstevel@tonic-gate {
36670Sstevel@tonic-gate 	struct modctl_list *lp, **lpp;
36680Sstevel@tonic-gate 
36690Sstevel@tonic-gate 	extern char *default_path;
36700Sstevel@tonic-gate 
36710Sstevel@tonic-gate 	/*
36720Sstevel@tonic-gate 	 * module_path can be set in /etc/system
36730Sstevel@tonic-gate 	 */
36740Sstevel@tonic-gate 	if (default_path != NULL)
36750Sstevel@tonic-gate 		module_path = default_path;
36760Sstevel@tonic-gate 	else
36770Sstevel@tonic-gate 		default_path = module_path;
36780Sstevel@tonic-gate 
36790Sstevel@tonic-gate 	ksyms_arena = vmem_create("ksyms", NULL, 0, sizeof (uint64_t),
36800Sstevel@tonic-gate 	    segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
36810Sstevel@tonic-gate 
36820Sstevel@tonic-gate 	ctf_arena = vmem_create("ctf", NULL, 0, sizeof (uint_t),
36830Sstevel@tonic-gate 	    segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
36840Sstevel@tonic-gate 
36850Sstevel@tonic-gate 	/*
36860Sstevel@tonic-gate 	 * Move symbol tables from boot memory to ksyms_arena.
36870Sstevel@tonic-gate 	 */
36880Sstevel@tonic-gate 	for (lpp = kobj_linkmaps; *lpp != NULL; lpp++) {
36890Sstevel@tonic-gate 		for (lp = *lpp; lp != NULL; lp = lp->modl_next)
36900Sstevel@tonic-gate 			kobj_export_module(mod(lp));
36910Sstevel@tonic-gate 	}
36920Sstevel@tonic-gate }
36930Sstevel@tonic-gate 
36940Sstevel@tonic-gate caddr_t
36950Sstevel@tonic-gate kobj_segbrk(caddr_t *spp, size_t size, size_t align, caddr_t limit)
36960Sstevel@tonic-gate {
36970Sstevel@tonic-gate 	uintptr_t va, pva;
36980Sstevel@tonic-gate 	size_t alloc_pgsz = kobj_mmu_pagesize;
36990Sstevel@tonic-gate 	size_t alloc_align = BO_NO_ALIGN;
37000Sstevel@tonic-gate 	size_t alloc_size;
37010Sstevel@tonic-gate 
37020Sstevel@tonic-gate 	/*
37030Sstevel@tonic-gate 	 * If we are using "large" mappings for the kernel,
37040Sstevel@tonic-gate 	 * request aligned memory from boot using the
37050Sstevel@tonic-gate 	 * "large" pagesize.
37060Sstevel@tonic-gate 	 */
37070Sstevel@tonic-gate 	if (lg_pagesize) {
37080Sstevel@tonic-gate 		alloc_align = lg_pagesize;
37090Sstevel@tonic-gate 		alloc_pgsz = lg_pagesize;
37100Sstevel@tonic-gate 	}
37110Sstevel@tonic-gate 	va = ALIGN((uintptr_t)*spp, align);
37120Sstevel@tonic-gate 	pva = P2ROUNDUP((uintptr_t)*spp, alloc_pgsz);
37130Sstevel@tonic-gate 	/*
37140Sstevel@tonic-gate 	 * Need more pages?
37150Sstevel@tonic-gate 	 */
37160Sstevel@tonic-gate 	if (va + size > pva) {
37170Sstevel@tonic-gate 		alloc_size = P2ROUNDUP(size - (pva - va), alloc_pgsz);
37180Sstevel@tonic-gate 		/*
37190Sstevel@tonic-gate 		 * Check for overlapping segments.
37200Sstevel@tonic-gate 		 */
37210Sstevel@tonic-gate 		if (limit && limit <= *spp + alloc_size)
37220Sstevel@tonic-gate 			return ((caddr_t)0);
37230Sstevel@tonic-gate 
37240Sstevel@tonic-gate 		pva = (uintptr_t)BOP_ALLOC(ops, (caddr_t)pva,
37250Sstevel@tonic-gate 					alloc_size, alloc_align);
37260Sstevel@tonic-gate 		if (pva == NULL) {
37270Sstevel@tonic-gate 			_kobj_printf(ops, "BOP_ALLOC refused, 0x%x bytes ",
37280Sstevel@tonic-gate 			    alloc_size);
37290Sstevel@tonic-gate 			_kobj_printf(ops, " at 0x%lx\n", pva);
37300Sstevel@tonic-gate 		}
37310Sstevel@tonic-gate 	}
37320Sstevel@tonic-gate 	*spp = (caddr_t)(va + size);
37330Sstevel@tonic-gate 
37340Sstevel@tonic-gate 	return ((caddr_t)va);
37350Sstevel@tonic-gate }
37360Sstevel@tonic-gate 
37370Sstevel@tonic-gate /*
37380Sstevel@tonic-gate  * Calculate the number of output hash buckets.
37390Sstevel@tonic-gate  * We use the next prime larger than n / 4,
37400Sstevel@tonic-gate  * so the average hash chain is about 4 entries.
37410Sstevel@tonic-gate  * More buckets would just be a waste of memory.
37420Sstevel@tonic-gate  */
37430Sstevel@tonic-gate uint_t
37440Sstevel@tonic-gate kobj_gethashsize(uint_t n)
37450Sstevel@tonic-gate {
37460Sstevel@tonic-gate 	int f;
37470Sstevel@tonic-gate 	int hsize = MAX(n / 4, 2);
37480Sstevel@tonic-gate 
37490Sstevel@tonic-gate 	for (f = 2; f * f <= hsize; f++)
37500Sstevel@tonic-gate 		if (hsize % f == 0)
37510Sstevel@tonic-gate 			hsize += f = 1;
37520Sstevel@tonic-gate 
37530Sstevel@tonic-gate 	return (hsize);
37540Sstevel@tonic-gate }
37550Sstevel@tonic-gate 
37560Sstevel@tonic-gate static char *
37570Sstevel@tonic-gate basename(char *s)
37580Sstevel@tonic-gate {
37590Sstevel@tonic-gate 	char *p, *q;
37600Sstevel@tonic-gate 
37610Sstevel@tonic-gate 	q = NULL;
37620Sstevel@tonic-gate 	p = s;
37630Sstevel@tonic-gate 	do {
37640Sstevel@tonic-gate 		if (*p == '/')
37650Sstevel@tonic-gate 			q = p;
37660Sstevel@tonic-gate 	} while (*p++);
37670Sstevel@tonic-gate 	return (q ? q + 1 : s);
37680Sstevel@tonic-gate }
37690Sstevel@tonic-gate 
37700Sstevel@tonic-gate /*ARGSUSED*/
37710Sstevel@tonic-gate static void
37720Sstevel@tonic-gate kprintf(void *op, const char *fmt, ...)
37730Sstevel@tonic-gate {
37740Sstevel@tonic-gate 	va_list adx;
37750Sstevel@tonic-gate 
37760Sstevel@tonic-gate 	va_start(adx, fmt);
37770Sstevel@tonic-gate 	vprintf(fmt, adx);
37780Sstevel@tonic-gate 	va_end(adx);
37790Sstevel@tonic-gate }
37800Sstevel@tonic-gate 
37810Sstevel@tonic-gate void
37820Sstevel@tonic-gate kobj_stat_get(kobj_stat_t *kp)
37830Sstevel@tonic-gate {
37840Sstevel@tonic-gate 	*kp = kobj_stat;
37850Sstevel@tonic-gate }
37860Sstevel@tonic-gate 
37870Sstevel@tonic-gate int
37880Sstevel@tonic-gate kobj_getpagesize()
37890Sstevel@tonic-gate {
37900Sstevel@tonic-gate 	return (lg_pagesize);
37910Sstevel@tonic-gate }
37920Sstevel@tonic-gate 
37930Sstevel@tonic-gate void
37940Sstevel@tonic-gate kobj_textwin_alloc(struct module *mp)
37950Sstevel@tonic-gate {
37960Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&mod_lock));
37970Sstevel@tonic-gate 
37980Sstevel@tonic-gate 	if (mp->textwin != NULL)
37990Sstevel@tonic-gate 		return;
38000Sstevel@tonic-gate 
38010Sstevel@tonic-gate 	/*
38020Sstevel@tonic-gate 	 * If the text is not contained in the heap, then it is not contained
38030Sstevel@tonic-gate 	 * by a writable mapping.  (Specifically, it's on the nucleus page.)
38040Sstevel@tonic-gate 	 * We allocate a read/write mapping for this module's text to allow
38050Sstevel@tonic-gate 	 * the text to be patched without calling hot_patch_kernel_text()
38060Sstevel@tonic-gate 	 * (which is quite slow).
38070Sstevel@tonic-gate 	 */
38080Sstevel@tonic-gate 	if (!vmem_contains(heaptext_arena, mp->text, mp->text_size)) {
38090Sstevel@tonic-gate 		uintptr_t text = (uintptr_t)mp->text;
38100Sstevel@tonic-gate 		uintptr_t size = (uintptr_t)mp->text_size;
38110Sstevel@tonic-gate 		uintptr_t i;
38120Sstevel@tonic-gate 		caddr_t va;
38130Sstevel@tonic-gate 		size_t sz = ((text + size + PAGESIZE - 1) & PAGEMASK) -
38140Sstevel@tonic-gate 		    (text & PAGEMASK);
38150Sstevel@tonic-gate 
38160Sstevel@tonic-gate 		va = mp->textwin_base = vmem_alloc(heap_arena, sz, VM_SLEEP);
38170Sstevel@tonic-gate 
38180Sstevel@tonic-gate 		for (i = text & PAGEMASK; i < text + size; i += PAGESIZE) {
38190Sstevel@tonic-gate 			hat_devload(kas.a_hat, va, PAGESIZE,
38200Sstevel@tonic-gate 			    hat_getpfnum(kas.a_hat, (caddr_t)i),
38210Sstevel@tonic-gate 			    PROT_READ | PROT_WRITE,
38220Sstevel@tonic-gate 			    HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
38230Sstevel@tonic-gate 			va += PAGESIZE;
38240Sstevel@tonic-gate 		}
38250Sstevel@tonic-gate 
38260Sstevel@tonic-gate 		mp->textwin = mp->textwin_base + (text & PAGEOFFSET);
38270Sstevel@tonic-gate 	} else {
38280Sstevel@tonic-gate 		mp->textwin = mp->text;
38290Sstevel@tonic-gate 	}
38300Sstevel@tonic-gate }
38310Sstevel@tonic-gate 
38320Sstevel@tonic-gate void
38330Sstevel@tonic-gate kobj_textwin_free(struct module *mp)
38340Sstevel@tonic-gate {
38350Sstevel@tonic-gate 	uintptr_t text = (uintptr_t)mp->text;
38360Sstevel@tonic-gate 	uintptr_t tsize = (uintptr_t)mp->text_size;
38370Sstevel@tonic-gate 	size_t size = (((text + tsize + PAGESIZE - 1) & PAGEMASK) -
38380Sstevel@tonic-gate 	    (text & PAGEMASK));
38390Sstevel@tonic-gate 
38400Sstevel@tonic-gate 	mp->textwin = NULL;
38410Sstevel@tonic-gate 
38420Sstevel@tonic-gate 	if (mp->textwin_base == NULL)
38430Sstevel@tonic-gate 		return;
38440Sstevel@tonic-gate 
38450Sstevel@tonic-gate 	hat_unload(kas.a_hat, mp->textwin_base, size, HAT_UNLOAD_UNLOCK);
38460Sstevel@tonic-gate 	vmem_free(heap_arena, mp->textwin_base, size);
38470Sstevel@tonic-gate 	mp->textwin_base = NULL;
38480Sstevel@tonic-gate }
38490Sstevel@tonic-gate 
38500Sstevel@tonic-gate static char *
38510Sstevel@tonic-gate find_libmacro(char *name)
38520Sstevel@tonic-gate {
38530Sstevel@tonic-gate 	int lmi;
38540Sstevel@tonic-gate 
38550Sstevel@tonic-gate 	for (lmi = 0; lmi < NLIBMACROS; lmi++) {
38560Sstevel@tonic-gate 		if (strcmp(name, libmacros[lmi].lmi_macroname) == 0)
38570Sstevel@tonic-gate 			return (libmacros[lmi].lmi_list);
38580Sstevel@tonic-gate 	}
38590Sstevel@tonic-gate 	return (NULL);
38600Sstevel@tonic-gate }
38610Sstevel@tonic-gate 
38620Sstevel@tonic-gate /*
38630Sstevel@tonic-gate  * Check for $MACRO in tail (string to expand) and expand it in path at pathend
38640Sstevel@tonic-gate  * returns path if successful, else NULL
38650Sstevel@tonic-gate  * Support multiple $MACROs expansion and the first valid path will be returned
38660Sstevel@tonic-gate  * Caller's responsibility to provide enough space in path to expand
38670Sstevel@tonic-gate  */
38680Sstevel@tonic-gate char *
38690Sstevel@tonic-gate expand_libmacro(char *tail, char *path, char *pathend)
38700Sstevel@tonic-gate {
38710Sstevel@tonic-gate 	char c, *p, *p1, *p2, *path2, *endp;
38720Sstevel@tonic-gate 	int diff, lmi, macrolen, valid_macro, more_macro;
38730Sstevel@tonic-gate 	struct _buf *file;
38740Sstevel@tonic-gate 
38750Sstevel@tonic-gate 	/*
38760Sstevel@tonic-gate 	 * check for $MACROS between nulls or slashes
38770Sstevel@tonic-gate 	 */
38780Sstevel@tonic-gate 	p = strchr(tail, '$');
38790Sstevel@tonic-gate 	if (p == NULL)
38800Sstevel@tonic-gate 		return (NULL);
38810Sstevel@tonic-gate 	for (lmi = 0; lmi < NLIBMACROS; lmi++) {
38820Sstevel@tonic-gate 		macrolen = libmacros[lmi].lmi_macrolen;
38830Sstevel@tonic-gate 		if (strncmp(p + 1, libmacros[lmi].lmi_macroname, macrolen) == 0)
38840Sstevel@tonic-gate 			break;
38850Sstevel@tonic-gate 	}
38860Sstevel@tonic-gate 
38870Sstevel@tonic-gate 	valid_macro = 0;
38880Sstevel@tonic-gate 	if (lmi < NLIBMACROS) {
38890Sstevel@tonic-gate 		/*
38900Sstevel@tonic-gate 		 * The following checks are used to restrict expansion of
38910Sstevel@tonic-gate 		 * macros to those that form a full directory/file name
38920Sstevel@tonic-gate 		 * and to keep the behavior same as before.  If this
38930Sstevel@tonic-gate 		 * restriction is removed or no longer valid in the future,
38940Sstevel@tonic-gate 		 * the checks below can be deleted.
38950Sstevel@tonic-gate 		 */
38960Sstevel@tonic-gate 		if ((p == tail) || (*(p - 1) == '/')) {
38970Sstevel@tonic-gate 			c = *(p + macrolen + 1);
38980Sstevel@tonic-gate 			if (c == '/' || c == '\0')
38990Sstevel@tonic-gate 				valid_macro = 1;
39000Sstevel@tonic-gate 		}
39010Sstevel@tonic-gate 	}
39020Sstevel@tonic-gate 
39030Sstevel@tonic-gate 	if (!valid_macro) {
39040Sstevel@tonic-gate 		p2 = strchr(p, '/');
39050Sstevel@tonic-gate 		/*
39060Sstevel@tonic-gate 		 * if no more macro to expand, then just copy whatever left
39070Sstevel@tonic-gate 		 * and check whether it exists
39080Sstevel@tonic-gate 		 */
39090Sstevel@tonic-gate 		if (p2 == NULL || strchr(p2, '$') == NULL) {
39100Sstevel@tonic-gate 			(void) strcpy(pathend, tail);
39110Sstevel@tonic-gate 			if ((file = kobj_open_path(path, 1, 1)) !=
39120Sstevel@tonic-gate 			    (struct _buf *)-1) {
39130Sstevel@tonic-gate 				kobj_close_file(file);
39140Sstevel@tonic-gate 				return (path);
39150Sstevel@tonic-gate 			} else
39160Sstevel@tonic-gate 				return (NULL);
39170Sstevel@tonic-gate 		} else {
39180Sstevel@tonic-gate 			/*
39190Sstevel@tonic-gate 			 * copy all chars before '/' and call expand_libmacro()
39200Sstevel@tonic-gate 			 * again
39210Sstevel@tonic-gate 			 */
39220Sstevel@tonic-gate 			diff = p2 - tail;
39230Sstevel@tonic-gate 			bcopy(tail, pathend, diff);
39240Sstevel@tonic-gate 			pathend += diff;
39250Sstevel@tonic-gate 			*(pathend) = '\0';
39260Sstevel@tonic-gate 			return (expand_libmacro(p2, path, pathend));
39270Sstevel@tonic-gate 		}
39280Sstevel@tonic-gate 	}
39290Sstevel@tonic-gate 
39300Sstevel@tonic-gate 	more_macro = 0;
39310Sstevel@tonic-gate 	if (c != '\0') {
39320Sstevel@tonic-gate 		endp = p + macrolen + 1;
39330Sstevel@tonic-gate 		if (strchr(endp, '$') != NULL)
39340Sstevel@tonic-gate 			more_macro = 1;
39350Sstevel@tonic-gate 	} else
39360Sstevel@tonic-gate 		endp = NULL;
39370Sstevel@tonic-gate 
39380Sstevel@tonic-gate 	/*
39390Sstevel@tonic-gate 	 * copy lmi_list and split it into components.
39400Sstevel@tonic-gate 	 * then put the part of tail before $MACRO into path
39410Sstevel@tonic-gate 	 * at pathend
39420Sstevel@tonic-gate 	 */
39430Sstevel@tonic-gate 	diff = p - tail;
39440Sstevel@tonic-gate 	if (diff > 0)
39450Sstevel@tonic-gate 		bcopy(tail, pathend, diff);
39460Sstevel@tonic-gate 	path2 = pathend + diff;
39470Sstevel@tonic-gate 	p1 = libmacros[lmi].lmi_list;
39480Sstevel@tonic-gate 	while (p1 && (*p1 != '\0')) {
39490Sstevel@tonic-gate 		p2 = strchr(p1, ':');
39500Sstevel@tonic-gate 		if (p2) {
39510Sstevel@tonic-gate 			diff = p2 - p1;
39520Sstevel@tonic-gate 			bcopy(p1, path2, diff);
39530Sstevel@tonic-gate 			*(path2 + diff) = '\0';
39540Sstevel@tonic-gate 		} else {
39550Sstevel@tonic-gate 			diff = strlen(p1);
39560Sstevel@tonic-gate 			bcopy(p1, path2, diff + 1);
39570Sstevel@tonic-gate 		}
39580Sstevel@tonic-gate 		/* copy endp only if there isn't any more macro to expand */
39590Sstevel@tonic-gate 		if (!more_macro && (endp != NULL))
39600Sstevel@tonic-gate 			(void) strcat(path2, endp);
39610Sstevel@tonic-gate 		file = kobj_open_path(path, 1, 1);
39620Sstevel@tonic-gate 		if (file != (struct _buf *)-1) {
39630Sstevel@tonic-gate 			kobj_close_file(file);
39640Sstevel@tonic-gate 			/*
39650Sstevel@tonic-gate 			 * if more macros to expand then call expand_libmacro(),
39660Sstevel@tonic-gate 			 * else return path which has the whole path
39670Sstevel@tonic-gate 			 */
39680Sstevel@tonic-gate 			if (!more_macro || (expand_libmacro(endp, path,
39690Sstevel@tonic-gate 			    path2 + diff) != NULL)) {
39700Sstevel@tonic-gate 				return (path);
39710Sstevel@tonic-gate 			}
39720Sstevel@tonic-gate 		}
39730Sstevel@tonic-gate 		if (p2)
39740Sstevel@tonic-gate 			p1 = ++p2;
39750Sstevel@tonic-gate 		else
39760Sstevel@tonic-gate 			return (NULL);
39770Sstevel@tonic-gate 	}
39780Sstevel@tonic-gate 	return (NULL);
39790Sstevel@tonic-gate }
39800Sstevel@tonic-gate 
39810Sstevel@tonic-gate static void
39820Sstevel@tonic-gate tnf_add_notifyunload(kobj_notify_f *fp)
39830Sstevel@tonic-gate {
39840Sstevel@tonic-gate 	kobj_notify_list_t *entry;
39850Sstevel@tonic-gate 
39860Sstevel@tonic-gate 	entry = kobj_alloc(sizeof (kobj_notify_list_t), KM_WAIT);
39870Sstevel@tonic-gate 	entry->kn_type = KOBJ_NOTIFY_MODUNLOADING;
39880Sstevel@tonic-gate 	entry->kn_func = fp;
39890Sstevel@tonic-gate 	(void) kobj_notify_add(entry);
39900Sstevel@tonic-gate }
39910Sstevel@tonic-gate 
39920Sstevel@tonic-gate /* ARGSUSED */
39930Sstevel@tonic-gate static void
39940Sstevel@tonic-gate tnf_unsplice_probes(unsigned int what, struct modctl *mod)
39950Sstevel@tonic-gate {
39960Sstevel@tonic-gate 	extern tnf_probe_control_t *__tnf_probe_list_head;
39970Sstevel@tonic-gate 	extern tnf_tag_data_t *__tnf_tag_list_head;
39980Sstevel@tonic-gate 	tnf_probe_control_t **p;
39990Sstevel@tonic-gate 	tnf_tag_data_t **q;
40000Sstevel@tonic-gate 	struct module *mp = mod->mod_mp;
40010Sstevel@tonic-gate 
40020Sstevel@tonic-gate 	if (!(mp->flags & KOBJ_TNF_PROBE))
40030Sstevel@tonic-gate 		return;
40040Sstevel@tonic-gate 
40050Sstevel@tonic-gate 	for (p = &__tnf_probe_list_head; *p; )
40060Sstevel@tonic-gate 		if (kobj_addrcheck(mp, (char *)*p) == 0)
40070Sstevel@tonic-gate 			*p = (*p)->next;
40080Sstevel@tonic-gate 		else
40090Sstevel@tonic-gate 			p = &(*p)->next;
40100Sstevel@tonic-gate 
40110Sstevel@tonic-gate 	for (q = &__tnf_tag_list_head; *q; )
40120Sstevel@tonic-gate 		if (kobj_addrcheck(mp, (char *)*q) == 0)
40130Sstevel@tonic-gate 			*q = (tnf_tag_data_t *)(*q)->tag_version;
40140Sstevel@tonic-gate 		else
40150Sstevel@tonic-gate 			q = (tnf_tag_data_t **)&(*q)->tag_version;
40160Sstevel@tonic-gate 
40170Sstevel@tonic-gate 	tnf_changed_probe_list = 1;
40180Sstevel@tonic-gate }
40190Sstevel@tonic-gate 
40200Sstevel@tonic-gate int
40210Sstevel@tonic-gate tnf_splice_probes(int boot_load, tnf_probe_control_t *plist,
40220Sstevel@tonic-gate     tnf_tag_data_t *tlist)
40230Sstevel@tonic-gate {
40240Sstevel@tonic-gate 	int result = 0;
40250Sstevel@tonic-gate 	static int add_notify = 1;
40260Sstevel@tonic-gate 
40270Sstevel@tonic-gate 	if (plist) {
40280Sstevel@tonic-gate 		tnf_probe_control_t *pl;
40290Sstevel@tonic-gate 
40300Sstevel@tonic-gate 		for (pl = plist; pl->next; )
40310Sstevel@tonic-gate 			pl = pl->next;
40320Sstevel@tonic-gate 
40330Sstevel@tonic-gate 		if (!boot_load)
40340Sstevel@tonic-gate 			mutex_enter(&mod_lock);
40350Sstevel@tonic-gate 		tnf_changed_probe_list = 1;
40360Sstevel@tonic-gate 		pl->next = __tnf_probe_list_head;
40370Sstevel@tonic-gate 		__tnf_probe_list_head = plist;
40380Sstevel@tonic-gate 		if (!boot_load)
40390Sstevel@tonic-gate 			mutex_exit(&mod_lock);
40400Sstevel@tonic-gate 		result = 1;
40410Sstevel@tonic-gate 	}
40420Sstevel@tonic-gate 
40430Sstevel@tonic-gate 	if (tlist) {
40440Sstevel@tonic-gate 		tnf_tag_data_t *tl;
40450Sstevel@tonic-gate 
40460Sstevel@tonic-gate 		for (tl = tlist; tl->tag_version; )
40470Sstevel@tonic-gate 			tl = (tnf_tag_data_t *)tl->tag_version;
40480Sstevel@tonic-gate 
40490Sstevel@tonic-gate 		if (!boot_load)
40500Sstevel@tonic-gate 			mutex_enter(&mod_lock);
40510Sstevel@tonic-gate 		tl->tag_version = (tnf_tag_version_t *)__tnf_tag_list_head;
40520Sstevel@tonic-gate 		__tnf_tag_list_head = tlist;
40530Sstevel@tonic-gate 		if (!boot_load)
40540Sstevel@tonic-gate 			mutex_exit(&mod_lock);
40550Sstevel@tonic-gate 		result = 1;
40560Sstevel@tonic-gate 	}
40570Sstevel@tonic-gate 	if (!boot_load && result && add_notify) {
40580Sstevel@tonic-gate 		tnf_add_notifyunload(tnf_unsplice_probes);
40590Sstevel@tonic-gate 		add_notify = 0;
40600Sstevel@tonic-gate 	}
40610Sstevel@tonic-gate 	return (result);
40620Sstevel@tonic-gate }
40630Sstevel@tonic-gate 
40640Sstevel@tonic-gate #if defined(__x86)
40650Sstevel@tonic-gate /*
40660Sstevel@tonic-gate  * This code is for the purpose of manually recording which files
40670Sstevel@tonic-gate  * needs to go into the boot archive on any given system.
40680Sstevel@tonic-gate  *
40690Sstevel@tonic-gate  * To enable the code, set kobj_file_bufsize in /etc/system
40700Sstevel@tonic-gate  * and reboot the system, then use mdb to look at kobj_file_buf.
40710Sstevel@tonic-gate  */
40720Sstevel@tonic-gate static void
40730Sstevel@tonic-gate kobj_record_file(char *filename)
40740Sstevel@tonic-gate {
40750Sstevel@tonic-gate 	extern char *kobj_file_buf;
40760Sstevel@tonic-gate 	extern int kobj_file_bufsize;
40770Sstevel@tonic-gate 	static char *buf;
40780Sstevel@tonic-gate 	static int size = 0;
40790Sstevel@tonic-gate 	int n;
40800Sstevel@tonic-gate 
40810Sstevel@tonic-gate 	if (standalone)		/* kernel symbol not available */
40820Sstevel@tonic-gate 		return;
40830Sstevel@tonic-gate 
40840Sstevel@tonic-gate 	if (kobj_file_bufsize == 0)	/* don't bother */
40850Sstevel@tonic-gate 		return;
40860Sstevel@tonic-gate 
40870Sstevel@tonic-gate 	if (kobj_file_buf == NULL) {	/* allocate buffer */
40880Sstevel@tonic-gate 		size = kobj_file_bufsize;
40890Sstevel@tonic-gate 		buf = kobj_file_buf = kobj_alloc(size, KM_WAIT|KM_TMP);
40900Sstevel@tonic-gate 	}
40910Sstevel@tonic-gate 
40920Sstevel@tonic-gate 	n = snprintf(buf, size, "%s\n", filename);
40930Sstevel@tonic-gate 	if (n > size)
40940Sstevel@tonic-gate 		n = size;
40950Sstevel@tonic-gate 	size -= n;
40960Sstevel@tonic-gate 	buf += n;
40970Sstevel@tonic-gate }
40980Sstevel@tonic-gate #endif	/* __x86 */
40990Sstevel@tonic-gate 
41000Sstevel@tonic-gate /*
41010Sstevel@tonic-gate  * XXX these wrappers should go away when sparc is converted
41020Sstevel@tonic-gate  * boot from ramdisk
41030Sstevel@tonic-gate  */
41040Sstevel@tonic-gate static int
41050Sstevel@tonic-gate kobj_boot_open(char *filename, int flags)
41060Sstevel@tonic-gate {
41070Sstevel@tonic-gate #if defined(__sparc)
41080Sstevel@tonic-gate 	/*
41090Sstevel@tonic-gate 	 * If io via bootops is quiesced, it means boot is no longer
41100Sstevel@tonic-gate 	 * available to us.  We make it look as if we can't open the
41110Sstevel@tonic-gate 	 * named file - which is reasonably accurate.
41120Sstevel@tonic-gate 	 */
41130Sstevel@tonic-gate 	if (!standalone && _ioquiesced)
41140Sstevel@tonic-gate 		return (-1);
41150Sstevel@tonic-gate 
41160Sstevel@tonic-gate 	return (BOP_OPEN(ops, filename, flags));
41170Sstevel@tonic-gate #else /* x86 */
41180Sstevel@tonic-gate 	kobj_record_file(filename);
41190Sstevel@tonic-gate 	return (BRD_OPEN(bfs_ops, filename, flags));
41200Sstevel@tonic-gate #endif
41210Sstevel@tonic-gate }
41220Sstevel@tonic-gate 
41230Sstevel@tonic-gate static int
41240Sstevel@tonic-gate kobj_boot_close(int fd)
41250Sstevel@tonic-gate {
41260Sstevel@tonic-gate #if defined(__sparc)
41270Sstevel@tonic-gate 	if (!standalone && _ioquiesced)
41280Sstevel@tonic-gate 		return (-1);
41290Sstevel@tonic-gate 
41300Sstevel@tonic-gate 	return (BOP_CLOSE(ops, fd));
41310Sstevel@tonic-gate #else /* x86 */
41320Sstevel@tonic-gate 	return (BRD_CLOSE(bfs_ops, fd));
41330Sstevel@tonic-gate #endif
41340Sstevel@tonic-gate }
41350Sstevel@tonic-gate 
41360Sstevel@tonic-gate /*ARGSUSED*/
41370Sstevel@tonic-gate static int
41380Sstevel@tonic-gate kobj_boot_seek(int fd, off_t hi, off_t lo)
41390Sstevel@tonic-gate {
41400Sstevel@tonic-gate #if defined(__sparc)
41410Sstevel@tonic-gate 	return (BOP_SEEK(ops, fd, hi, lo));
41420Sstevel@tonic-gate #else
41430Sstevel@tonic-gate 	return (BRD_SEEK(bfs_ops, fd, lo, SEEK_SET));
41440Sstevel@tonic-gate #endif
41450Sstevel@tonic-gate }
41460Sstevel@tonic-gate 
41470Sstevel@tonic-gate static int
41480Sstevel@tonic-gate kobj_boot_read(int fd, caddr_t buf, size_t size)
41490Sstevel@tonic-gate {
41500Sstevel@tonic-gate #if defined(__sparc)
41510Sstevel@tonic-gate 	return (BOP_READ(ops, fd, buf, size));
41520Sstevel@tonic-gate #else
41530Sstevel@tonic-gate 	return (BRD_READ(bfs_ops, fd, buf, size));
41540Sstevel@tonic-gate #endif
41550Sstevel@tonic-gate }
4156