xref: /titanic_52/usr/src/cmd/sgs/libld/common/ldmain.c (revision 1007fd6fd24227460e77ce89f5ca85641a85a576)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
26*1007fd6fSAli Bahrami  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
30ba2be530Sab196087  * Processing of relocatable objects and shared objects.
31ba2be530Sab196087  */
32ba2be530Sab196087 
33ba2be530Sab196087 /*
347c478bd9Sstevel@tonic-gate  * ld -- link/editor main program
357c478bd9Sstevel@tonic-gate  */
365aefb655Srie #include	<sys/types.h>
372017c965SRod Evans #include	<sys/time.h>
385aefb655Srie #include	<sys/mman.h>
397c478bd9Sstevel@tonic-gate #include	<string.h>
407c478bd9Sstevel@tonic-gate #include	<stdio.h>
417c478bd9Sstevel@tonic-gate #include	<locale.h>
427c478bd9Sstevel@tonic-gate #include	<stdarg.h>
435aefb655Srie #include	<debug.h>
447c478bd9Sstevel@tonic-gate #include	"msg.h"
457c478bd9Sstevel@tonic-gate #include	"_libld.h"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
48ba2be530Sab196087  * All target specific code is referenced via this global variable, which
49ba2be530Sab196087  * is initialized in ld_main(). This allows the linker to function as
50ba2be530Sab196087  * a cross linker, by vectoring to the target-specific code for the
51ba2be530Sab196087  * current target machine.
52ba2be530Sab196087  */
53ba2be530Sab196087 Target		ld_targ;
54ba2be530Sab196087 
55ba2be530Sab196087 /*
565aefb655Srie  * A default library search path is used if one was not supplied on the command
575aefb655Srie  * line.  Note: these strings can not use MSG_ORIG() since they are modified as
585aefb655Srie  * part of the path processing.
597c478bd9Sstevel@tonic-gate  */
605aefb655Srie #if	defined(_ELF64)
617c478bd9Sstevel@tonic-gate static char	def_Plibpath[] = "/lib/64:/usr/lib/64";
627c478bd9Sstevel@tonic-gate #else
637c478bd9Sstevel@tonic-gate static char	def_Plibpath[] = "/usr/ccs/lib:/lib:/usr/lib";
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /*
675aefb655Srie  * A default elf header provides for simplifying diagnostic processing.
685aefb655Srie  */
695aefb655Srie static Ehdr	def_ehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
70ba2be530Sab196087 			    ELFCLASSNONE, ELFDATANONE }, 0, EM_NONE,
71ba2be530Sab196087 			    EV_CURRENT };
72ba2be530Sab196087 
73ba2be530Sab196087 /*
74*1007fd6fSAli Bahrami  * ld-centric wrapper on top of veprintf():
75*1007fd6fSAli Bahrami  * - Accepts output descriptor rather than linkmap list
76*1007fd6fSAli Bahrami  * - Sets the FLG_OF_FATAL/FLG_OF_WARN flags as necessary
77*1007fd6fSAli Bahrami  */
78*1007fd6fSAli Bahrami void
79*1007fd6fSAli Bahrami ld_eprintf(Ofl_desc *ofl, Error error, const char *format, ...)
80*1007fd6fSAli Bahrami {
81*1007fd6fSAli Bahrami 	va_list	args;
82*1007fd6fSAli Bahrami 
83*1007fd6fSAli Bahrami 	/* Set flag indicating type of error being issued */
84*1007fd6fSAli Bahrami 	switch (error) {
85*1007fd6fSAli Bahrami 	case ERR_NONE:
86*1007fd6fSAli Bahrami 	case ERR_WARNING_NF:
87*1007fd6fSAli Bahrami 		break;
88*1007fd6fSAli Bahrami 	case ERR_WARNING:
89*1007fd6fSAli Bahrami 		ofl->ofl_flags |= FLG_OF_WARN;
90*1007fd6fSAli Bahrami 		break;
91*1007fd6fSAli Bahrami 	case ERR_GUIDANCE:
92*1007fd6fSAli Bahrami 		if ((ofl->ofl_guideflags & FLG_OFG_ENABLE) == 0)
93*1007fd6fSAli Bahrami 			return;
94*1007fd6fSAli Bahrami 		ofl->ofl_guideflags |= FLG_OFG_ISSUED;
95*1007fd6fSAli Bahrami 		ofl->ofl_flags |= FLG_OF_WARN;
96*1007fd6fSAli Bahrami 		break;
97*1007fd6fSAli Bahrami 	default:
98*1007fd6fSAli Bahrami 		ofl->ofl_flags |= FLG_OF_FATAL;
99*1007fd6fSAli Bahrami 	}
100*1007fd6fSAli Bahrami 
101*1007fd6fSAli Bahrami 	/* Issue the error */
102*1007fd6fSAli Bahrami 	va_start(args, format);
103*1007fd6fSAli Bahrami 	veprintf(ofl->ofl_lml, error, format, args);
104*1007fd6fSAli Bahrami 	va_end(args);
105*1007fd6fSAli Bahrami }
106*1007fd6fSAli Bahrami 
107*1007fd6fSAli Bahrami /*
108ba2be530Sab196087  * Establish the global state necessary to link the desired machine
109ba2be530Sab196087  * target, as reflected by the ld_targ global variable.
110ba2be530Sab196087  */
111ba2be530Sab196087 int
112ba2be530Sab196087 ld_init_target(Lm_list *lml, Half mach)
113ba2be530Sab196087 {
114ba2be530Sab196087 	switch (mach) {
115ba2be530Sab196087 	case EM_386:
116ba2be530Sab196087 	case EM_AMD64:
117ba2be530Sab196087 		ld_targ = *ld_targ_init_x86();
118ba2be530Sab196087 		break;
119ba2be530Sab196087 
120ba2be530Sab196087 	case EM_SPARC:
121ba2be530Sab196087 	case EM_SPARC32PLUS:
122ba2be530Sab196087 	case EM_SPARCV9:
123ba2be530Sab196087 		ld_targ = *ld_targ_init_sparc();
124ba2be530Sab196087 		break;
125ba2be530Sab196087 
126ba2be530Sab196087 	default:
127ba2be530Sab196087 		{
128ba2be530Sab196087 			Conv_inv_buf_t	inv_buf;
129ba2be530Sab196087 
130ba2be530Sab196087 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TARG_UNSUPPORTED),
131ba2be530Sab196087 			    conv_ehdr_mach(mach, 0, &inv_buf));
132ba2be530Sab196087 			return (1);
133ba2be530Sab196087 		}
134ba2be530Sab196087 	}
135ba2be530Sab196087 
136ba2be530Sab196087 	return (0);
137ba2be530Sab196087 }
138ba2be530Sab196087 
1395aefb655Srie 
1405aefb655Srie /*
1417c478bd9Sstevel@tonic-gate  * The main program
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate int
144ba2be530Sab196087 ld_main(int argc, char **argv, Half mach)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate 	char		*sgs_support;	/* SGS_SUPPORT environment string */
1477c478bd9Sstevel@tonic-gate 	Half		etype;
1485aefb655Srie 	Ofl_desc	*ofl;
149*1007fd6fSAli Bahrami 	ofl_flag_t	save_flg_of_warn;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/*
1522017c965SRod Evans 	 * Establish a base time.  Total time diagnostics are relative to
1532017c965SRod Evans 	 * entering the link-editor here.
1542017c965SRod Evans 	 */
1552017c965SRod Evans 	(void) gettimeofday(&DBG_TOTALTIME, NULL);
1562017c965SRod Evans 	DBG_DELTATIME = DBG_TOTALTIME;
1572017c965SRod Evans 
15856e2cc86SAli Bahrami 	/* Output file descriptor */
1595aefb655Srie 	if ((ofl = libld_calloc(1, sizeof (Ofl_desc))) == 0)
1605aefb655Srie 		return (1);
1615aefb655Srie 
16256e2cc86SAli Bahrami 	/* Initialize target state */
163ba2be530Sab196087 	if (ld_init_target(NULL, mach) != 0)
164ba2be530Sab196087 		return (1);
165ba2be530Sab196087 
166ba2be530Sab196087 	/*
16756e2cc86SAli Bahrami 	 * Set up the default output ELF header to satisfy diagnostic
16856e2cc86SAli Bahrami 	 * requirements, and initialize the machine and class details.
169ba2be530Sab196087 	 */
1705aefb655Srie 	ofl->ofl_dehdr = &def_ehdr;
171ba2be530Sab196087 	def_ehdr.e_ident[EI_CLASS] = ld_targ.t_m.m_class;
172ba2be530Sab196087 	def_ehdr.e_ident[EI_DATA] = ld_targ.t_m.m_data;
173ba2be530Sab196087 	def_ehdr.e_machine = ld_targ.t_m.m_mach;
1745aefb655Srie 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Build up linker version string
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_sgsid = (char *)libld_calloc(MSG_SGS_ID_SIZE +
1797c478bd9Sstevel@tonic-gate 	    strlen(link_ver_string) + 1, 1)) == NULL)
1807c478bd9Sstevel@tonic-gate 		return (1);
1817c478bd9Sstevel@tonic-gate 	(void) strcpy(ofl->ofl_sgsid, MSG_ORIG(MSG_SGS_ID));
1827c478bd9Sstevel@tonic-gate 	(void) strcat(ofl->ofl_sgsid, link_ver_string);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/*
1857c478bd9Sstevel@tonic-gate 	 * Argument pass one.  Get all the input flags (skip any files) and
18657ef7aa9SRod Evans 	 * check for consistency.  Return from ld_process_flags() marks the
18757ef7aa9SRod Evans 	 * end of mapfile processing.  The entrance criteria and segment
18857ef7aa9SRod Evans 	 * descriptors are complete and in their final form.
1897c478bd9Sstevel@tonic-gate 	 */
190*1007fd6fSAli Bahrami 	if (ld_process_flags(ofl, argc, argv) == S_ERROR) {
191*1007fd6fSAli Bahrami 		/* If any ERR_GUIDANCE messages were issued, add a summary */
192*1007fd6fSAli Bahrami 		if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
193*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_GUIDANCE,
194*1007fd6fSAli Bahrami 			    MSG_INTL(MSG_GUIDE_SUMMARY));
1957c478bd9Sstevel@tonic-gate 		return (1);
196*1007fd6fSAli Bahrami 	}
1977c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_FATAL) {
198*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FLAGS));
199*1007fd6fSAli Bahrami 		/* If any ERR_GUIDANCE messages were issued, add a summary */
200*1007fd6fSAli Bahrami 		if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
201*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_GUIDANCE,
202*1007fd6fSAli Bahrami 			    MSG_INTL(MSG_GUIDE_SUMMARY));
2037c478bd9Sstevel@tonic-gate 		return (1);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/*
2077c478bd9Sstevel@tonic-gate 	 * At this point a call such as ld -V is considered complete.
2087c478bd9Sstevel@tonic-gate 	 */
2097c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags1 & FLG_OF1_DONE)
2107c478bd9Sstevel@tonic-gate 		return (0);
2117c478bd9Sstevel@tonic-gate 
21256e2cc86SAli Bahrami 	/* Initialize signal handler */
21356e2cc86SAli Bahrami 	ld_init_sighandler(ofl);
21456e2cc86SAli Bahrami 
2157c478bd9Sstevel@tonic-gate 	/*
216d2d5cf7cSAli Bahrami 	 * Determine whether any support libraries should be loaded,
217d2d5cf7cSAli Bahrami 	 * (either through the SGS_SUPPORT environment variable and/or
218d2d5cf7cSAli Bahrami 	 * through the -S option).
2197c478bd9Sstevel@tonic-gate 	 */
2207c478bd9Sstevel@tonic-gate #if	defined(_LP64)
2217c478bd9Sstevel@tonic-gate 	if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_64))) == NULL)
2227c478bd9Sstevel@tonic-gate #else
2237c478bd9Sstevel@tonic-gate 	if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_32))) == NULL)
2247c478bd9Sstevel@tonic-gate #endif
2257c478bd9Sstevel@tonic-gate 		sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT));
2267c478bd9Sstevel@tonic-gate 
22798c080d5SRod Evans 	if (sgs_support && sgs_support[0]) {
2287c478bd9Sstevel@tonic-gate 		const char	*sep = MSG_ORIG(MSG_STR_COLON);
2297c478bd9Sstevel@tonic-gate 		char		*lib;
2307c478bd9Sstevel@tonic-gate 		char		*lasts;
2317c478bd9Sstevel@tonic-gate 
2325aefb655Srie 		DBG_CALL(Dbg_support_req(ofl->ofl_lml, sgs_support,
2335aefb655Srie 		    DBG_SUP_ENVIRON));
2347c478bd9Sstevel@tonic-gate 		if ((lib = strtok_r(sgs_support, sep, &lasts)) != NULL) {
2357c478bd9Sstevel@tonic-gate 			do {
2365aefb655Srie 				if (ld_sup_loadso(ofl, lib) == S_ERROR)
2375aefb655Srie 					return (ld_exit(ofl));
2382017c965SRod Evans 				DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 			} while ((lib = strtok_r(NULL, sep, &lasts)) != NULL);
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 	}
24357ef7aa9SRod Evans 	if (lib_support) {
24457ef7aa9SRod Evans 		Aliste	idx;
2457c478bd9Sstevel@tonic-gate 		char	*lib;
2467c478bd9Sstevel@tonic-gate 
24757ef7aa9SRod Evans 		for (APLIST_TRAVERSE(lib_support, idx, lib)) {
2485aefb655Srie 			DBG_CALL(Dbg_support_req(ofl->ofl_lml, lib,
2495aefb655Srie 			    DBG_SUP_CMDLINE));
2505aefb655Srie 			if (ld_sup_loadso(ofl, lib) == S_ERROR)
2515aefb655Srie 				return (ld_exit(ofl));
2522926dd2eSrie 			DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2532017c965SRod Evans 		}
2542017c965SRod Evans 	}
2557c478bd9Sstevel@tonic-gate 
2564f680cc6SAli Bahrami 	DBG_CALL(Dbg_ent_print(ofl->ofl_lml,
2574f680cc6SAli Bahrami 	    ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
25869112eddSAli Bahrami 	    ofl->ofl_ents));
2594f680cc6SAli Bahrami 	DBG_CALL(Dbg_seg_list(ofl->ofl_lml,
2604f680cc6SAli Bahrami 	    ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
26157ef7aa9SRod Evans 	    ofl->ofl_segs));
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	/*
2647c478bd9Sstevel@tonic-gate 	 * The objscnt and soscnt variables were used to estimate the expected
2657c478bd9Sstevel@tonic-gate 	 * input files, and size the symbol hash buckets accordingly.  Reset
2667c478bd9Sstevel@tonic-gate 	 * these values now, so as to gain an accurate count from pass two, for
2677c478bd9Sstevel@tonic-gate 	 * later statistics diagnostics.
2687c478bd9Sstevel@tonic-gate 	 */
2697c478bd9Sstevel@tonic-gate 	ofl->ofl_objscnt = ofl->ofl_soscnt = 0;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	/*
2727c478bd9Sstevel@tonic-gate 	 * Determine whether we can create the file before going any further.
2737c478bd9Sstevel@tonic-gate 	 */
2745aefb655Srie 	if (ld_open_outfile(ofl) == S_ERROR)
2755aefb655Srie 		return (ld_exit(ofl));
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	/*
2787c478bd9Sstevel@tonic-gate 	 * If the user didn't supply a library path supply a default.  And, if
2797c478bd9Sstevel@tonic-gate 	 * no run-path has been specified (-R), see if the environment variable
280bb3b4f6cSRod Evans 	 * is in use (historic).
2817c478bd9Sstevel@tonic-gate 	 */
2827c478bd9Sstevel@tonic-gate 	if (Plibpath == NULL)
2837c478bd9Sstevel@tonic-gate 		Plibpath = def_Plibpath;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (ofl->ofl_rpath == NULL) {
2867c478bd9Sstevel@tonic-gate 		char	*rpath;
28798c080d5SRod Evans 
2887c478bd9Sstevel@tonic-gate 		if (((rpath = getenv(MSG_ORIG(MSG_LD_RUN_PATH))) != NULL) &&
28998c080d5SRod Evans 		    rpath[0])
2907c478bd9Sstevel@tonic-gate 			ofl->ofl_rpath = rpath;
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * Argument pass two.  Input all libraries and objects.
2957c478bd9Sstevel@tonic-gate 	 */
2965aefb655Srie 	if (ld_lib_setup(ofl) == S_ERROR)
2975aefb655Srie 		return (ld_exit(ofl));
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	/*
3007c478bd9Sstevel@tonic-gate 	 * Call ld_start() with the etype of our output file and the
3017c478bd9Sstevel@tonic-gate 	 * output file name.
3027c478bd9Sstevel@tonic-gate 	 */
3037c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
3047c478bd9Sstevel@tonic-gate 		etype = ET_DYN;
3057c478bd9Sstevel@tonic-gate 	else if (ofl->ofl_flags & FLG_OF_RELOBJ)
3067c478bd9Sstevel@tonic-gate 		etype = ET_REL;
3077c478bd9Sstevel@tonic-gate 	else
3087c478bd9Sstevel@tonic-gate 		etype = ET_EXEC;
3097c478bd9Sstevel@tonic-gate 
3105aefb655Srie 	ld_sup_start(ofl, etype, argv[0]);
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/*
3137c478bd9Sstevel@tonic-gate 	 * Process all input files.
3147c478bd9Sstevel@tonic-gate 	 */
3155aefb655Srie 	if (ld_process_files(ofl, argc, argv) == S_ERROR)
3165aefb655Srie 		return (ld_exit(ofl));
3177c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_FATAL) {
318*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FILES),
3195aefb655Srie 		    ofl->ofl_name);
3205aefb655Srie 		return (ld_exit(ofl));
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
3235aefb655Srie 	ld_sup_input_done(ofl);
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	/*
32657ef7aa9SRod Evans 	 * Now that all input section processing is complete, validate and
32757ef7aa9SRod Evans 	 * process any SHT_SUNW_move sections.
3287c478bd9Sstevel@tonic-gate 	 */
32957ef7aa9SRod Evans 	if (ofl->ofl_ismove && (ld_process_move(ofl) == S_ERROR))
3305aefb655Srie 		return (ld_exit(ofl));
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/*
3337c478bd9Sstevel@tonic-gate 	 * Before validating all symbols count the number of relocation entries.
3347c478bd9Sstevel@tonic-gate 	 * If copy relocations exist, COMMON symbols must be generated which are
3357c478bd9Sstevel@tonic-gate 	 * assigned to the executables .bss.  During sym_validate() the actual
3367c478bd9Sstevel@tonic-gate 	 * size and alignment of the .bss is calculated.  Doing things in this
3377c478bd9Sstevel@tonic-gate 	 * order reduces the number of symbol table traversals required (however
3387c478bd9Sstevel@tonic-gate 	 * it does take a little longer for the user to be told of any undefined
3397c478bd9Sstevel@tonic-gate 	 * symbol errors).
3407c478bd9Sstevel@tonic-gate 	 */
3415aefb655Srie 	if (ld_reloc_init(ofl) == S_ERROR)
3425aefb655Srie 		return (ld_exit(ofl));
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	/*
345*1007fd6fSAli Bahrami 	 * We need to know if FLG_OF_WARN is currently set, in case
346*1007fd6fSAli Bahrami 	 * we need to honor a -z fatal-warnings request. However, we also
347*1007fd6fSAli Bahrami 	 * need to know if a warning due to symbol validation results from
348*1007fd6fSAli Bahrami 	 * the upcoming call to ld_sym_validate() in order to issue the
349*1007fd6fSAli Bahrami 	 * appropriate message for it. So we save the current value,
350*1007fd6fSAli Bahrami 	 * and clear the main flag.
351*1007fd6fSAli Bahrami 	 */
352*1007fd6fSAli Bahrami 	save_flg_of_warn = ofl->ofl_flags & FLG_OF_WARN;
353*1007fd6fSAli Bahrami 	ofl->ofl_flags &= ~FLG_OF_WARN;
354*1007fd6fSAli Bahrami 
355*1007fd6fSAli Bahrami 	if (ld_sym_validate(ofl) == S_ERROR)
356*1007fd6fSAli Bahrami 		return (ld_exit(ofl));
357*1007fd6fSAli Bahrami 
358*1007fd6fSAli Bahrami 	/*
3597c478bd9Sstevel@tonic-gate 	 * Now that all symbol processing is complete see if any undefined
3607c478bd9Sstevel@tonic-gate 	 * references still remain.  If we observed undefined symbols the
3617c478bd9Sstevel@tonic-gate 	 * FLG_OF_FATAL bit will be set:  If creating a static executable, or a
3627c478bd9Sstevel@tonic-gate 	 * dynamic executable or shared object with the -zdefs flag set, this
3637c478bd9Sstevel@tonic-gate 	 * condition is fatal.  If creating a shared object with the -Bsymbolic
3647c478bd9Sstevel@tonic-gate 	 * flag set, this condition is simply a warning.
3657c478bd9Sstevel@tonic-gate 	 */
366*1007fd6fSAli Bahrami 	if (ofl->ofl_flags & FLG_OF_FATAL)
367*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_SYM_FATAL),
368*1007fd6fSAli Bahrami 		    ofl->ofl_name);
369*1007fd6fSAli Bahrami 	else if (ofl->ofl_flags & FLG_OF_WARN)
370*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ARG_SYM_WARN));
3717c478bd9Sstevel@tonic-gate 
372*1007fd6fSAli Bahrami 	/*
373*1007fd6fSAli Bahrami 	 * Guidance: Use -z defs|nodefs when building shared objects.
374*1007fd6fSAli Bahrami 	 *
375*1007fd6fSAli Bahrami 	 * ld_sym_validate() will mask this guidance message out unless we are
376*1007fd6fSAli Bahrami 	 * intended to send it here, so all we need to do is use OFL_GUIDANCE()
377*1007fd6fSAli Bahrami 	 * to decide whether to issue it or not.
378*1007fd6fSAli Bahrami 	 */
379*1007fd6fSAli Bahrami 	if (OFL_GUIDANCE(ofl, FLG_OFG_NO_DEFS))
380*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_DEFS));
381*1007fd6fSAli Bahrami 
382*1007fd6fSAli Bahrami 	/*
383*1007fd6fSAli Bahrami 	 * Symbol processing was the final step before we start producing the
384*1007fd6fSAli Bahrami 	 * output object. At this time, if we've seen warnings and the
385*1007fd6fSAli Bahrami 	 * -z fatal-warnings option is specified, promote them to fatal, which
386*1007fd6fSAli Bahrami 	 * will cause us to exit without creating an object.
387*1007fd6fSAli Bahrami 	 *
388*1007fd6fSAli Bahrami 	 * We didn't do this as the warnings were reported in order to
389*1007fd6fSAli Bahrami 	 * maximize the number of problems a given link-editor invocation
390*1007fd6fSAli Bahrami 	 * can diagnose. This is safe, since warnings are by definition events
391*1007fd6fSAli Bahrami 	 * one can choose to ignore.
392*1007fd6fSAli Bahrami 	 */
393*1007fd6fSAli Bahrami 	if (((ofl->ofl_flags | save_flg_of_warn) &
394*1007fd6fSAli Bahrami 	    (FLG_OF_WARN | FLG_OF_FATWARN)) ==
395*1007fd6fSAli Bahrami 	    (FLG_OF_WARN | FLG_OF_FATWARN))
396*1007fd6fSAli Bahrami 		ofl->ofl_flags |= FLG_OF_FATAL;
397*1007fd6fSAli Bahrami 
398*1007fd6fSAli Bahrami 	/*
399*1007fd6fSAli Bahrami 	 * If fatal errors occurred in symbol processing, or due to warnings
400*1007fd6fSAli Bahrami 	 * promoted by -z fatal-warnings, this is the end of the line.
401*1007fd6fSAli Bahrami 	 */
402*1007fd6fSAli Bahrami 	if (ofl->ofl_flags & FLG_OF_FATAL)
4035aefb655Srie 		return (ld_exit(ofl));
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/*
4067c478bd9Sstevel@tonic-gate 	 * Generate any necessary sections.
4077c478bd9Sstevel@tonic-gate 	 */
4085aefb655Srie 	if (ld_make_sections(ofl) == S_ERROR)
4095aefb655Srie 		return (ld_exit(ofl));
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/*
4120e233487SRod Evans 	 * Now that all sections have been added to the output file, determine
4130e233487SRod Evans 	 * whether any mapfile section ordering was specified, and verify that
4140e233487SRod Evans 	 * all mapfile ordering directives have been matched.  Issue a warning
4150e233487SRod Evans 	 * for any directives that have not been matched.
4167c478bd9Sstevel@tonic-gate 	 * Also, if SHF_ORDERED sections exist, set up sort key values.
4177c478bd9Sstevel@tonic-gate 	 */
41869112eddSAli Bahrami 	if (ofl->ofl_flags & (FLG_OF_OS_ORDER | FLG_OF_KEY))
4195aefb655Srie 		ld_sec_validate(ofl);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/*
4227c478bd9Sstevel@tonic-gate 	 * Having collected all the input data create the initial output file
4237c478bd9Sstevel@tonic-gate 	 * image, assign virtual addresses to the image, and generate a load
4247c478bd9Sstevel@tonic-gate 	 * map if the user requested one.
4257c478bd9Sstevel@tonic-gate 	 */
4265aefb655Srie 	if (ld_create_outfile(ofl) == S_ERROR)
4275aefb655Srie 		return (ld_exit(ofl));
4287c478bd9Sstevel@tonic-gate 
4295aefb655Srie 	if (ld_update_outfile(ofl) == S_ERROR)
4305aefb655Srie 		return (ld_exit(ofl));
4317c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_GENMAP)
4325aefb655Srie 		ld_map_out(ofl);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/*
4357c478bd9Sstevel@tonic-gate 	 * Build relocation sections and perform any relocation updates.
4367c478bd9Sstevel@tonic-gate 	 */
4375aefb655Srie 	if (ld_reloc_process(ofl) == S_ERROR)
4385aefb655Srie 		return (ld_exit(ofl));
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/*
4417e16fca0SAli Bahrami 	 * Fill in contents for unwind header (.eh_frame_hdr)
4427c478bd9Sstevel@tonic-gate 	 */
4437e16fca0SAli Bahrami 	if (ld_unwind_populate_hdr(ofl) == S_ERROR)
4445aefb655Srie 		return (ld_exit(ofl));
445ba2be530Sab196087 
4467c478bd9Sstevel@tonic-gate 	/*
4477c478bd9Sstevel@tonic-gate 	 * Finally create the files elf checksum.
4487c478bd9Sstevel@tonic-gate 	 */
4497c478bd9Sstevel@tonic-gate 	if (ofl->ofl_checksum)
4507c478bd9Sstevel@tonic-gate 		*ofl->ofl_checksum = (Xword)elf_checksum(ofl->ofl_elf);
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/*
453ba2be530Sab196087 	 * If this is a cross link to a target with a different byte
454ba2be530Sab196087 	 * order than the linker, swap the data to the target byte order.
455ba2be530Sab196087 	 */
456ba2be530Sab196087 	if (((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) &&
457ba2be530Sab196087 	    (_elf_swap_wrimage(ofl->ofl_elf) != 0)) {
458*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_SWAP_WRIMAGE),
459ba2be530Sab196087 		    ofl->ofl_name);
460ba2be530Sab196087 		return (ld_exit(ofl));
461ba2be530Sab196087 	}
462ba2be530Sab196087 
463ba2be530Sab196087 	/*
4647c478bd9Sstevel@tonic-gate 	 * We're done, so make sure the updates are flushed to the output file.
4657c478bd9Sstevel@tonic-gate 	 */
4667c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_size = elf_update(ofl->ofl_welf, ELF_C_WRITE)) == 0) {
467*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_UPDATE),
4685aefb655Srie 		    ofl->ofl_name);
4695aefb655Srie 		return (ld_exit(ofl));
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4725aefb655Srie 	ld_sup_atexit(ofl, 0);
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	DBG_CALL(Dbg_statistics_ld(ofl));
4752017c965SRod Evans 	DBG_CALL(Dbg_basic_finish(ofl->ofl_lml));
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/*
478e23c41c9SAli Bahrami 	 * Wrap up debug output file if one is open
479e23c41c9SAli Bahrami 	 */
480e23c41c9SAli Bahrami 	dbg_cleanup();
481e23c41c9SAli Bahrami 
482*1007fd6fSAli Bahrami 	/* If any ERR_GUIDANCE messages were issued, add a summary */
483*1007fd6fSAli Bahrami 	if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
484*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_SUMMARY));
485*1007fd6fSAli Bahrami 
486e23c41c9SAli Bahrami 	/*
4877c478bd9Sstevel@tonic-gate 	 * For performance reasons we don't actually free up the memory we've
4887c478bd9Sstevel@tonic-gate 	 * allocated, it will be freed when we exit.
4897c478bd9Sstevel@tonic-gate 	 *
4907c478bd9Sstevel@tonic-gate 	 * But the below line can be uncommented if/when we want to measure how
4917c478bd9Sstevel@tonic-gate 	 * our memory consumption and freeing are doing.  We should be able to
4927c478bd9Sstevel@tonic-gate 	 * free all the memory that has been allocated as part of the link-edit
4937c478bd9Sstevel@tonic-gate 	 * process.
4947c478bd9Sstevel@tonic-gate 	 */
495cdcc71c0SAli Bahrami 	/* ld_ofl_cleanup(ofl); */
4967c478bd9Sstevel@tonic-gate 	return (0);
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4995aefb655Srie /*
5005aefb655Srie  * Cleanup an Ifl_desc.
5015aefb655Srie  */
5025aefb655Srie static void
50357ef7aa9SRod Evans ifl_list_cleanup(APlist *apl)
5047c478bd9Sstevel@tonic-gate {
50557ef7aa9SRod Evans 	Aliste		idx;
5065aefb655Srie 	Ifl_desc	*ifl;
5077c478bd9Sstevel@tonic-gate 
50857ef7aa9SRod Evans 	for (APLIST_TRAVERSE(apl, idx, ifl)) {
5095aefb655Srie 		if (ifl->ifl_elf)
5105aefb655Srie 			(void) elf_end(ifl->ifl_elf);
51157ef7aa9SRod Evans 	}
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate /*
5155aefb655Srie  * Cleanup all memory that has been dynamically allocated during libld
5165aefb655Srie  * processing and elf_end() all Elf descriptors that are still open.
5177c478bd9Sstevel@tonic-gate  */
5185aefb655Srie void
5195aefb655Srie ld_ofl_cleanup(Ofl_desc *ofl)
5205aefb655Srie {
5215aefb655Srie 	Ld_heap		*chp, *php;
5225aefb655Srie 	Ar_desc		*adp;
52357ef7aa9SRod Evans 	Aliste		idx;
5247c478bd9Sstevel@tonic-gate 
52557ef7aa9SRod Evans 	ifl_list_cleanup(ofl->ofl_objs);
52657ef7aa9SRod Evans 	ofl->ofl_objs = NULL;
52757ef7aa9SRod Evans 	ifl_list_cleanup(ofl->ofl_sos);
52857ef7aa9SRod Evans 	ofl->ofl_sos = NULL;
5295aefb655Srie 
53057ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_ars, idx, adp)) {
5315aefb655Srie 		Ar_aux		*aup;
5325aefb655Srie 		Elf_Arsym	*arsym;
5335aefb655Srie 
5345aefb655Srie 		for (arsym = adp->ad_start, aup = adp->ad_aux;
5355aefb655Srie 		    arsym->as_name; ++arsym, ++aup) {
5365aefb655Srie 			if ((aup->au_mem) && (aup->au_mem != FLG_ARMEM_PROC)) {
5375aefb655Srie 				(void) elf_end(aup->au_mem->am_elf);
5385aefb655Srie 
5395aefb655Srie 				/*
5405aefb655Srie 				 * Null out all entries to this member so
5415aefb655Srie 				 * that we don't attempt to elf_end() it again.
5425aefb655Srie 				 */
5435aefb655Srie 				ld_ar_member(adp, arsym, aup, 0);
5445aefb655Srie 			}
5455aefb655Srie 		}
5465aefb655Srie 		(void) elf_end(adp->ad_elf);
5475aefb655Srie 	}
54857ef7aa9SRod Evans 	ofl->ofl_ars = NULL;
5495aefb655Srie 
5505aefb655Srie 	(void) elf_end(ofl->ofl_elf);
5515aefb655Srie 	(void) elf_end(ofl->ofl_welf);
5525aefb655Srie 
55357ef7aa9SRod Evans 	for (chp = ld_heap, php = NULL; chp; php = chp, chp = chp->lh_next) {
5545aefb655Srie 		if (php)
5555aefb655Srie 			(void) munmap((void *)php,
5565aefb655Srie 			    (size_t)php->lh_end - (size_t)php);
5575aefb655Srie 	}
5585aefb655Srie 	if (php)
5595aefb655Srie 		(void) munmap((void *)php, (size_t)php->lh_end - (size_t)php);
5605aefb655Srie 
56157ef7aa9SRod Evans 	ld_heap = NULL;
5627c478bd9Sstevel@tonic-gate }
563