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