xref: /onnv-gate/usr/src/cmd/sgs/libld/common/ldmain.c (revision 13074:787bf65954d0)
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
51618Srie  * Common Development and Distribution License (the "License").
61618Srie  * 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  */
211618Srie 
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
240Sstevel@tonic-gate  *	  All Rights Reserved
250Sstevel@tonic-gate  *
26*13074SAli.Bahrami@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
306206Sab196087  * Processing of relocatable objects and shared objects.
316206Sab196087  */
326206Sab196087 
336206Sab196087 /*
340Sstevel@tonic-gate  * ld -- link/editor main program
350Sstevel@tonic-gate  */
361618Srie #include	<sys/types.h>
379577SRod.Evans@Sun.COM #include	<sys/time.h>
381618Srie #include	<sys/mman.h>
390Sstevel@tonic-gate #include	<string.h>
400Sstevel@tonic-gate #include	<stdio.h>
410Sstevel@tonic-gate #include	<locale.h>
420Sstevel@tonic-gate #include	<stdarg.h>
431618Srie #include	<debug.h>
440Sstevel@tonic-gate #include	"msg.h"
450Sstevel@tonic-gate #include	"_libld.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
486206Sab196087  * All target specific code is referenced via this global variable, which
496206Sab196087  * is initialized in ld_main(). This allows the linker to function as
506206Sab196087  * a cross linker, by vectoring to the target-specific code for the
516206Sab196087  * current target machine.
526206Sab196087  */
536206Sab196087 Target		ld_targ;
546206Sab196087 
556206Sab196087 /*
561618Srie  * A default library search path is used if one was not supplied on the command
571618Srie  * line.  Note: these strings can not use MSG_ORIG() since they are modified as
581618Srie  * part of the path processing.
590Sstevel@tonic-gate  */
601618Srie #if	defined(_ELF64)
610Sstevel@tonic-gate static char	def_Plibpath[] = "/lib/64:/usr/lib/64";
620Sstevel@tonic-gate #else
630Sstevel@tonic-gate static char	def_Plibpath[] = "/usr/ccs/lib:/lib:/usr/lib";
640Sstevel@tonic-gate #endif
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
671618Srie  * A default elf header provides for simplifying diagnostic processing.
681618Srie  */
691618Srie static Ehdr	def_ehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
706206Sab196087 			    ELFCLASSNONE, ELFDATANONE }, 0, EM_NONE,
716206Sab196087 			    EV_CURRENT };
726206Sab196087 
736206Sab196087 /*
74*13074SAli.Bahrami@Oracle.COM  * ld-centric wrapper on top of veprintf():
75*13074SAli.Bahrami@Oracle.COM  * - Accepts output descriptor rather than linkmap list
76*13074SAli.Bahrami@Oracle.COM  * - Sets the FLG_OF_FATAL/FLG_OF_WARN flags as necessary
77*13074SAli.Bahrami@Oracle.COM  */
78*13074SAli.Bahrami@Oracle.COM void
ld_eprintf(Ofl_desc * ofl,Error error,const char * format,...)79*13074SAli.Bahrami@Oracle.COM ld_eprintf(Ofl_desc *ofl, Error error, const char *format, ...)
80*13074SAli.Bahrami@Oracle.COM {
81*13074SAli.Bahrami@Oracle.COM 	va_list	args;
82*13074SAli.Bahrami@Oracle.COM 
83*13074SAli.Bahrami@Oracle.COM 	/* Set flag indicating type of error being issued */
84*13074SAli.Bahrami@Oracle.COM 	switch (error) {
85*13074SAli.Bahrami@Oracle.COM 	case ERR_NONE:
86*13074SAli.Bahrami@Oracle.COM 	case ERR_WARNING_NF:
87*13074SAli.Bahrami@Oracle.COM 		break;
88*13074SAli.Bahrami@Oracle.COM 	case ERR_WARNING:
89*13074SAli.Bahrami@Oracle.COM 		ofl->ofl_flags |= FLG_OF_WARN;
90*13074SAli.Bahrami@Oracle.COM 		break;
91*13074SAli.Bahrami@Oracle.COM 	case ERR_GUIDANCE:
92*13074SAli.Bahrami@Oracle.COM 		if ((ofl->ofl_guideflags & FLG_OFG_ENABLE) == 0)
93*13074SAli.Bahrami@Oracle.COM 			return;
94*13074SAli.Bahrami@Oracle.COM 		ofl->ofl_guideflags |= FLG_OFG_ISSUED;
95*13074SAli.Bahrami@Oracle.COM 		ofl->ofl_flags |= FLG_OF_WARN;
96*13074SAli.Bahrami@Oracle.COM 		break;
97*13074SAli.Bahrami@Oracle.COM 	default:
98*13074SAli.Bahrami@Oracle.COM 		ofl->ofl_flags |= FLG_OF_FATAL;
99*13074SAli.Bahrami@Oracle.COM 	}
100*13074SAli.Bahrami@Oracle.COM 
101*13074SAli.Bahrami@Oracle.COM 	/* Issue the error */
102*13074SAli.Bahrami@Oracle.COM 	va_start(args, format);
103*13074SAli.Bahrami@Oracle.COM 	veprintf(ofl->ofl_lml, error, format, args);
104*13074SAli.Bahrami@Oracle.COM 	va_end(args);
105*13074SAli.Bahrami@Oracle.COM }
106*13074SAli.Bahrami@Oracle.COM 
107*13074SAli.Bahrami@Oracle.COM /*
1086206Sab196087  * Establish the global state necessary to link the desired machine
1096206Sab196087  * target, as reflected by the ld_targ global variable.
1106206Sab196087  */
1116206Sab196087 int
ld_init_target(Lm_list * lml,Half mach)1126206Sab196087 ld_init_target(Lm_list *lml, Half mach)
1136206Sab196087 {
1146206Sab196087 	switch (mach) {
1156206Sab196087 	case EM_386:
1166206Sab196087 	case EM_AMD64:
1176206Sab196087 		ld_targ = *ld_targ_init_x86();
1186206Sab196087 		break;
1196206Sab196087 
1206206Sab196087 	case EM_SPARC:
1216206Sab196087 	case EM_SPARC32PLUS:
1226206Sab196087 	case EM_SPARCV9:
1236206Sab196087 		ld_targ = *ld_targ_init_sparc();
1246206Sab196087 		break;
1256206Sab196087 
1266206Sab196087 	default:
1276206Sab196087 		{
1286206Sab196087 			Conv_inv_buf_t	inv_buf;
1296206Sab196087 
1306206Sab196087 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TARG_UNSUPPORTED),
1316206Sab196087 			    conv_ehdr_mach(mach, 0, &inv_buf));
1326206Sab196087 			return (1);
1336206Sab196087 		}
1346206Sab196087 	}
1356206Sab196087 
1366206Sab196087 	return (0);
1376206Sab196087 }
1386206Sab196087 
1391618Srie 
1401618Srie /*
1410Sstevel@tonic-gate  * The main program
1420Sstevel@tonic-gate  */
1430Sstevel@tonic-gate int
ld_main(int argc,char ** argv,Half mach)1446206Sab196087 ld_main(int argc, char **argv, Half mach)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	char		*sgs_support;	/* SGS_SUPPORT environment string */
1470Sstevel@tonic-gate 	Half		etype;
1481618Srie 	Ofl_desc	*ofl;
149*13074SAli.Bahrami@Oracle.COM 	ofl_flag_t	save_flg_of_warn;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	/*
1529577SRod.Evans@Sun.COM 	 * Establish a base time.  Total time diagnostics are relative to
1539577SRod.Evans@Sun.COM 	 * entering the link-editor here.
1549577SRod.Evans@Sun.COM 	 */
1559577SRod.Evans@Sun.COM 	(void) gettimeofday(&DBG_TOTALTIME, NULL);
1569577SRod.Evans@Sun.COM 	DBG_DELTATIME = DBG_TOTALTIME;
1579577SRod.Evans@Sun.COM 
1589646SAli.Bahrami@Sun.COM 	/* Output file descriptor */
1591618Srie 	if ((ofl = libld_calloc(1, sizeof (Ofl_desc))) == 0)
1601618Srie 		return (1);
1611618Srie 
1629646SAli.Bahrami@Sun.COM 	/* Initialize target state */
1636206Sab196087 	if (ld_init_target(NULL, mach) != 0)
1646206Sab196087 		return (1);
1656206Sab196087 
1666206Sab196087 	/*
1679646SAli.Bahrami@Sun.COM 	 * Set up the default output ELF header to satisfy diagnostic
1689646SAli.Bahrami@Sun.COM 	 * requirements, and initialize the machine and class details.
1696206Sab196087 	 */
1701618Srie 	ofl->ofl_dehdr = &def_ehdr;
1716206Sab196087 	def_ehdr.e_ident[EI_CLASS] = ld_targ.t_m.m_class;
1726206Sab196087 	def_ehdr.e_ident[EI_DATA] = ld_targ.t_m.m_data;
1736206Sab196087 	def_ehdr.e_machine = ld_targ.t_m.m_mach;
1741618Srie 
1750Sstevel@tonic-gate 	/*
1760Sstevel@tonic-gate 	 * Build up linker version string
1770Sstevel@tonic-gate 	 */
1780Sstevel@tonic-gate 	if ((ofl->ofl_sgsid = (char *)libld_calloc(MSG_SGS_ID_SIZE +
1790Sstevel@tonic-gate 	    strlen(link_ver_string) + 1, 1)) == NULL)
1800Sstevel@tonic-gate 		return (1);
1810Sstevel@tonic-gate 	(void) strcpy(ofl->ofl_sgsid, MSG_ORIG(MSG_SGS_ID));
1820Sstevel@tonic-gate 	(void) strcat(ofl->ofl_sgsid, link_ver_string);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	/*
1850Sstevel@tonic-gate 	 * Argument pass one.  Get all the input flags (skip any files) and
1869131SRod.Evans@Sun.COM 	 * check for consistency.  Return from ld_process_flags() marks the
1879131SRod.Evans@Sun.COM 	 * end of mapfile processing.  The entrance criteria and segment
1889131SRod.Evans@Sun.COM 	 * descriptors are complete and in their final form.
1890Sstevel@tonic-gate 	 */
190*13074SAli.Bahrami@Oracle.COM 	if (ld_process_flags(ofl, argc, argv) == S_ERROR) {
191*13074SAli.Bahrami@Oracle.COM 		/* If any ERR_GUIDANCE messages were issued, add a summary */
192*13074SAli.Bahrami@Oracle.COM 		if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
193*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_GUIDANCE,
194*13074SAli.Bahrami@Oracle.COM 			    MSG_INTL(MSG_GUIDE_SUMMARY));
1950Sstevel@tonic-gate 		return (1);
196*13074SAli.Bahrami@Oracle.COM 	}
1970Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_FATAL) {
198*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FLAGS));
199*13074SAli.Bahrami@Oracle.COM 		/* If any ERR_GUIDANCE messages were issued, add a summary */
200*13074SAli.Bahrami@Oracle.COM 		if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
201*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_GUIDANCE,
202*13074SAli.Bahrami@Oracle.COM 			    MSG_INTL(MSG_GUIDE_SUMMARY));
2030Sstevel@tonic-gate 		return (1);
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	/*
2070Sstevel@tonic-gate 	 * At this point a call such as ld -V is considered complete.
2080Sstevel@tonic-gate 	 */
2090Sstevel@tonic-gate 	if (ofl->ofl_flags1 & FLG_OF1_DONE)
2100Sstevel@tonic-gate 		return (0);
2110Sstevel@tonic-gate 
2129646SAli.Bahrami@Sun.COM 	/* Initialize signal handler */
2139646SAli.Bahrami@Sun.COM 	ld_init_sighandler(ofl);
2149646SAli.Bahrami@Sun.COM 
2150Sstevel@tonic-gate 	/*
2168324SAli.Bahrami@Sun.COM 	 * Determine whether any support libraries should be loaded,
2178324SAli.Bahrami@Sun.COM 	 * (either through the SGS_SUPPORT environment variable and/or
2188324SAli.Bahrami@Sun.COM 	 * through the -S option).
2190Sstevel@tonic-gate 	 */
2200Sstevel@tonic-gate #if	defined(_LP64)
2210Sstevel@tonic-gate 	if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_64))) == NULL)
2220Sstevel@tonic-gate #else
2230Sstevel@tonic-gate 	if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_32))) == NULL)
2240Sstevel@tonic-gate #endif
2250Sstevel@tonic-gate 		sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT));
2260Sstevel@tonic-gate 
22712029SRod.Evans@Sun.COM 	if (sgs_support && sgs_support[0]) {
2280Sstevel@tonic-gate 		const char	*sep = MSG_ORIG(MSG_STR_COLON);
2290Sstevel@tonic-gate 		char		*lib;
2300Sstevel@tonic-gate 		char		*lasts;
2310Sstevel@tonic-gate 
2321618Srie 		DBG_CALL(Dbg_support_req(ofl->ofl_lml, sgs_support,
2331618Srie 		    DBG_SUP_ENVIRON));
2340Sstevel@tonic-gate 		if ((lib = strtok_r(sgs_support, sep, &lasts)) != NULL) {
2350Sstevel@tonic-gate 			do {
2361618Srie 				if (ld_sup_loadso(ofl, lib) == S_ERROR)
2371618Srie 					return (ld_exit(ofl));
2389577SRod.Evans@Sun.COM 				DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 			} while ((lib = strtok_r(NULL, sep, &lasts)) != NULL);
2410Sstevel@tonic-gate 		}
2420Sstevel@tonic-gate 	}
2439131SRod.Evans@Sun.COM 	if (lib_support) {
2449131SRod.Evans@Sun.COM 		Aliste	idx;
2459131SRod.Evans@Sun.COM 		char	*lib;
2460Sstevel@tonic-gate 
2479131SRod.Evans@Sun.COM 		for (APLIST_TRAVERSE(lib_support, idx, lib)) {
2481618Srie 			DBG_CALL(Dbg_support_req(ofl->ofl_lml, lib,
2491618Srie 			    DBG_SUP_CMDLINE));
2501618Srie 			if (ld_sup_loadso(ofl, lib) == S_ERROR)
2511618Srie 				return (ld_exit(ofl));
2529577SRod.Evans@Sun.COM 			DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2530Sstevel@tonic-gate 		}
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate 
2569273SAli.Bahrami@Sun.COM 	DBG_CALL(Dbg_ent_print(ofl->ofl_lml,
2579273SAli.Bahrami@Sun.COM 	    ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
25811734SAli.Bahrami@Sun.COM 	    ofl->ofl_ents));
2599273SAli.Bahrami@Sun.COM 	DBG_CALL(Dbg_seg_list(ofl->ofl_lml,
2609273SAli.Bahrami@Sun.COM 	    ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
2619131SRod.Evans@Sun.COM 	    ofl->ofl_segs));
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/*
2640Sstevel@tonic-gate 	 * The objscnt and soscnt variables were used to estimate the expected
2650Sstevel@tonic-gate 	 * input files, and size the symbol hash buckets accordingly.  Reset
2660Sstevel@tonic-gate 	 * these values now, so as to gain an accurate count from pass two, for
2670Sstevel@tonic-gate 	 * later statistics diagnostics.
2680Sstevel@tonic-gate 	 */
2690Sstevel@tonic-gate 	ofl->ofl_objscnt = ofl->ofl_soscnt = 0;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	/*
2720Sstevel@tonic-gate 	 * Determine whether we can create the file before going any further.
2730Sstevel@tonic-gate 	 */
2741618Srie 	if (ld_open_outfile(ofl) == S_ERROR)
2751618Srie 		return (ld_exit(ofl));
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	/*
2780Sstevel@tonic-gate 	 * If the user didn't supply a library path supply a default.  And, if
2790Sstevel@tonic-gate 	 * no run-path has been specified (-R), see if the environment variable
2808501SRod.Evans@Sun.COM 	 * is in use (historic).
2810Sstevel@tonic-gate 	 */
2820Sstevel@tonic-gate 	if (Plibpath == NULL)
2830Sstevel@tonic-gate 		Plibpath = def_Plibpath;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (ofl->ofl_rpath == NULL) {
28612029SRod.Evans@Sun.COM 		char	*rpath;
28712029SRod.Evans@Sun.COM 
2880Sstevel@tonic-gate 		if (((rpath = getenv(MSG_ORIG(MSG_LD_RUN_PATH))) != NULL) &&
28912029SRod.Evans@Sun.COM 		    rpath[0])
2900Sstevel@tonic-gate 			ofl->ofl_rpath = rpath;
2910Sstevel@tonic-gate 	}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	/*
2940Sstevel@tonic-gate 	 * Argument pass two.  Input all libraries and objects.
2950Sstevel@tonic-gate 	 */
2961618Srie 	if (ld_lib_setup(ofl) == S_ERROR)
2971618Srie 		return (ld_exit(ofl));
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	/*
3000Sstevel@tonic-gate 	 * Call ld_start() with the etype of our output file and the
3010Sstevel@tonic-gate 	 * output file name.
3020Sstevel@tonic-gate 	 */
3030Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
3040Sstevel@tonic-gate 		etype = ET_DYN;
3050Sstevel@tonic-gate 	else if (ofl->ofl_flags & FLG_OF_RELOBJ)
3060Sstevel@tonic-gate 		etype = ET_REL;
3070Sstevel@tonic-gate 	else
3080Sstevel@tonic-gate 		etype = ET_EXEC;
3090Sstevel@tonic-gate 
3101618Srie 	ld_sup_start(ofl, etype, argv[0]);
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	/*
3130Sstevel@tonic-gate 	 * Process all input files.
3140Sstevel@tonic-gate 	 */
3151618Srie 	if (ld_process_files(ofl, argc, argv) == S_ERROR)
3161618Srie 		return (ld_exit(ofl));
3170Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_FATAL) {
318*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FILES),
3191618Srie 		    ofl->ofl_name);
3201618Srie 		return (ld_exit(ofl));
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3231618Srie 	ld_sup_input_done(ofl);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	/*
3269131SRod.Evans@Sun.COM 	 * Now that all input section processing is complete, validate and
3279131SRod.Evans@Sun.COM 	 * process any SHT_SUNW_move sections.
3280Sstevel@tonic-gate 	 */
3299131SRod.Evans@Sun.COM 	if (ofl->ofl_ismove && (ld_process_move(ofl) == S_ERROR))
3309131SRod.Evans@Sun.COM 		return (ld_exit(ofl));
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	/*
3330Sstevel@tonic-gate 	 * Before validating all symbols count the number of relocation entries.
3340Sstevel@tonic-gate 	 * If copy relocations exist, COMMON symbols must be generated which are
3350Sstevel@tonic-gate 	 * assigned to the executables .bss.  During sym_validate() the actual
3360Sstevel@tonic-gate 	 * size and alignment of the .bss is calculated.  Doing things in this
3370Sstevel@tonic-gate 	 * order reduces the number of symbol table traversals required (however
3380Sstevel@tonic-gate 	 * it does take a little longer for the user to be told of any undefined
3390Sstevel@tonic-gate 	 * symbol errors).
3400Sstevel@tonic-gate 	 */
3411618Srie 	if (ld_reloc_init(ofl) == S_ERROR)
3421618Srie 		return (ld_exit(ofl));
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	/*
345*13074SAli.Bahrami@Oracle.COM 	 * We need to know if FLG_OF_WARN is currently set, in case
346*13074SAli.Bahrami@Oracle.COM 	 * we need to honor a -z fatal-warnings request. However, we also
347*13074SAli.Bahrami@Oracle.COM 	 * need to know if a warning due to symbol validation results from
348*13074SAli.Bahrami@Oracle.COM 	 * the upcoming call to ld_sym_validate() in order to issue the
349*13074SAli.Bahrami@Oracle.COM 	 * appropriate message for it. So we save the current value,
350*13074SAli.Bahrami@Oracle.COM 	 * and clear the main flag.
351*13074SAli.Bahrami@Oracle.COM 	 */
352*13074SAli.Bahrami@Oracle.COM 	save_flg_of_warn = ofl->ofl_flags & FLG_OF_WARN;
353*13074SAli.Bahrami@Oracle.COM 	ofl->ofl_flags &= ~FLG_OF_WARN;
354*13074SAli.Bahrami@Oracle.COM 
355*13074SAli.Bahrami@Oracle.COM 	if (ld_sym_validate(ofl) == S_ERROR)
356*13074SAli.Bahrami@Oracle.COM 		return (ld_exit(ofl));
357*13074SAli.Bahrami@Oracle.COM 
358*13074SAli.Bahrami@Oracle.COM 	/*
3590Sstevel@tonic-gate 	 * Now that all symbol processing is complete see if any undefined
3600Sstevel@tonic-gate 	 * references still remain.  If we observed undefined symbols the
3610Sstevel@tonic-gate 	 * FLG_OF_FATAL bit will be set:  If creating a static executable, or a
3620Sstevel@tonic-gate 	 * dynamic executable or shared object with the -zdefs flag set, this
3630Sstevel@tonic-gate 	 * condition is fatal.  If creating a shared object with the -Bsymbolic
3640Sstevel@tonic-gate 	 * flag set, this condition is simply a warning.
3650Sstevel@tonic-gate 	 */
366*13074SAli.Bahrami@Oracle.COM 	if (ofl->ofl_flags & FLG_OF_FATAL)
367*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_SYM_FATAL),
368*13074SAli.Bahrami@Oracle.COM 		    ofl->ofl_name);
369*13074SAli.Bahrami@Oracle.COM 	else if (ofl->ofl_flags & FLG_OF_WARN)
370*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ARG_SYM_WARN));
371*13074SAli.Bahrami@Oracle.COM 
372*13074SAli.Bahrami@Oracle.COM 	/*
373*13074SAli.Bahrami@Oracle.COM 	 * Guidance: Use -z defs|nodefs when building shared objects.
374*13074SAli.Bahrami@Oracle.COM 	 *
375*13074SAli.Bahrami@Oracle.COM 	 * ld_sym_validate() will mask this guidance message out unless we are
376*13074SAli.Bahrami@Oracle.COM 	 * intended to send it here, so all we need to do is use OFL_GUIDANCE()
377*13074SAli.Bahrami@Oracle.COM 	 * to decide whether to issue it or not.
378*13074SAli.Bahrami@Oracle.COM 	 */
379*13074SAli.Bahrami@Oracle.COM 	if (OFL_GUIDANCE(ofl, FLG_OFG_NO_DEFS))
380*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_DEFS));
3810Sstevel@tonic-gate 
382*13074SAli.Bahrami@Oracle.COM 	/*
383*13074SAli.Bahrami@Oracle.COM 	 * Symbol processing was the final step before we start producing the
384*13074SAli.Bahrami@Oracle.COM 	 * output object. At this time, if we've seen warnings and the
385*13074SAli.Bahrami@Oracle.COM 	 * -z fatal-warnings option is specified, promote them to fatal, which
386*13074SAli.Bahrami@Oracle.COM 	 * will cause us to exit without creating an object.
387*13074SAli.Bahrami@Oracle.COM 	 *
388*13074SAli.Bahrami@Oracle.COM 	 * We didn't do this as the warnings were reported in order to
389*13074SAli.Bahrami@Oracle.COM 	 * maximize the number of problems a given link-editor invocation
390*13074SAli.Bahrami@Oracle.COM 	 * can diagnose. This is safe, since warnings are by definition events
391*13074SAli.Bahrami@Oracle.COM 	 * one can choose to ignore.
392*13074SAli.Bahrami@Oracle.COM 	 */
393*13074SAli.Bahrami@Oracle.COM 	if (((ofl->ofl_flags | save_flg_of_warn) &
394*13074SAli.Bahrami@Oracle.COM 	    (FLG_OF_WARN | FLG_OF_FATWARN)) ==
395*13074SAli.Bahrami@Oracle.COM 	    (FLG_OF_WARN | FLG_OF_FATWARN))
396*13074SAli.Bahrami@Oracle.COM 		ofl->ofl_flags |= FLG_OF_FATAL;
397*13074SAli.Bahrami@Oracle.COM 
398*13074SAli.Bahrami@Oracle.COM 	/*
399*13074SAli.Bahrami@Oracle.COM 	 * If fatal errors occurred in symbol processing, or due to warnings
400*13074SAli.Bahrami@Oracle.COM 	 * promoted by -z fatal-warnings, this is the end of the line.
401*13074SAli.Bahrami@Oracle.COM 	 */
402*13074SAli.Bahrami@Oracle.COM 	if (ofl->ofl_flags & FLG_OF_FATAL)
4031618Srie 		return (ld_exit(ofl));
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	/*
4060Sstevel@tonic-gate 	 * Generate any necessary sections.
4070Sstevel@tonic-gate 	 */
4081618Srie 	if (ld_make_sections(ofl) == S_ERROR)
4091618Srie 		return (ld_exit(ofl));
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	/*
4127463SRod.Evans@Sun.COM 	 * Now that all sections have been added to the output file, determine
4137463SRod.Evans@Sun.COM 	 * whether any mapfile section ordering was specified, and verify that
4147463SRod.Evans@Sun.COM 	 * all mapfile ordering directives have been matched.  Issue a warning
4157463SRod.Evans@Sun.COM 	 * for any directives that have not been matched.
4160Sstevel@tonic-gate 	 * Also, if SHF_ORDERED sections exist, set up sort key values.
4170Sstevel@tonic-gate 	 */
41811734SAli.Bahrami@Sun.COM 	if (ofl->ofl_flags & (FLG_OF_OS_ORDER | FLG_OF_KEY))
4197463SRod.Evans@Sun.COM 		ld_sec_validate(ofl);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/*
4220Sstevel@tonic-gate 	 * Having collected all the input data create the initial output file
4230Sstevel@tonic-gate 	 * image, assign virtual addresses to the image, and generate a load
4240Sstevel@tonic-gate 	 * map if the user requested one.
4250Sstevel@tonic-gate 	 */
4261618Srie 	if (ld_create_outfile(ofl) == S_ERROR)
4271618Srie 		return (ld_exit(ofl));
4280Sstevel@tonic-gate 
4291618Srie 	if (ld_update_outfile(ofl) == S_ERROR)
4301618Srie 		return (ld_exit(ofl));
4310Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_GENMAP)
4321618Srie 		ld_map_out(ofl);
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	/*
4350Sstevel@tonic-gate 	 * Build relocation sections and perform any relocation updates.
4360Sstevel@tonic-gate 	 */
4371618Srie 	if (ld_reloc_process(ofl) == S_ERROR)
4381618Srie 		return (ld_exit(ofl));
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	/*
4419085SAli.Bahrami@Sun.COM 	 * Fill in contents for unwind header (.eh_frame_hdr)
4420Sstevel@tonic-gate 	 */
4439085SAli.Bahrami@Sun.COM 	if (ld_unwind_populate_hdr(ofl) == S_ERROR)
4441618Srie 		return (ld_exit(ofl));
4456206Sab196087 
4460Sstevel@tonic-gate 	/*
4470Sstevel@tonic-gate 	 * Finally create the files elf checksum.
4480Sstevel@tonic-gate 	 */
4490Sstevel@tonic-gate 	if (ofl->ofl_checksum)
4500Sstevel@tonic-gate 		*ofl->ofl_checksum = (Xword)elf_checksum(ofl->ofl_elf);
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	/*
4536206Sab196087 	 * If this is a cross link to a target with a different byte
4546206Sab196087 	 * order than the linker, swap the data to the target byte order.
4556206Sab196087 	 */
4566206Sab196087 	if (((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) &&
4576206Sab196087 	    (_elf_swap_wrimage(ofl->ofl_elf) != 0)) {
458*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_SWAP_WRIMAGE),
4596206Sab196087 		    ofl->ofl_name);
4606206Sab196087 		return (ld_exit(ofl));
4616206Sab196087 	}
4626206Sab196087 
4636206Sab196087 	/*
4640Sstevel@tonic-gate 	 * We're done, so make sure the updates are flushed to the output file.
4650Sstevel@tonic-gate 	 */
4660Sstevel@tonic-gate 	if ((ofl->ofl_size = elf_update(ofl->ofl_welf, ELF_C_WRITE)) == 0) {
467*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_UPDATE),
4681618Srie 		    ofl->ofl_name);
4691618Srie 		return (ld_exit(ofl));
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 
4721618Srie 	ld_sup_atexit(ofl, 0);
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	DBG_CALL(Dbg_statistics_ld(ofl));
4759577SRod.Evans@Sun.COM 	DBG_CALL(Dbg_basic_finish(ofl->ofl_lml));
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	/*
4789406SAli.Bahrami@Sun.COM 	 * Wrap up debug output file if one is open
4799406SAli.Bahrami@Sun.COM 	 */
4809406SAli.Bahrami@Sun.COM 	dbg_cleanup();
4819406SAli.Bahrami@Sun.COM 
482*13074SAli.Bahrami@Oracle.COM 	/* If any ERR_GUIDANCE messages were issued, add a summary */
483*13074SAli.Bahrami@Oracle.COM 	if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
484*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_SUMMARY));
485*13074SAli.Bahrami@Oracle.COM 
4869406SAli.Bahrami@Sun.COM 	/*
4870Sstevel@tonic-gate 	 * For performance reasons we don't actually free up the memory we've
4880Sstevel@tonic-gate 	 * allocated, it will be freed when we exit.
4890Sstevel@tonic-gate 	 *
4900Sstevel@tonic-gate 	 * But the below line can be uncommented if/when we want to measure how
4910Sstevel@tonic-gate 	 * our memory consumption and freeing are doing.  We should be able to
4920Sstevel@tonic-gate 	 * free all the memory that has been allocated as part of the link-edit
4930Sstevel@tonic-gate 	 * process.
4940Sstevel@tonic-gate 	 */
49510580SAli.Bahrami@Sun.COM 	/* ld_ofl_cleanup(ofl); */
4960Sstevel@tonic-gate 	return (0);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate 
4991618Srie /*
5001618Srie  * Cleanup an Ifl_desc.
5011618Srie  */
5021618Srie static void
ifl_list_cleanup(APlist * apl)5039131SRod.Evans@Sun.COM ifl_list_cleanup(APlist *apl)
5040Sstevel@tonic-gate {
5059131SRod.Evans@Sun.COM 	Aliste		idx;
5061618Srie 	Ifl_desc	*ifl;
5070Sstevel@tonic-gate 
5089131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(apl, idx, ifl)) {
5091618Srie 		if (ifl->ifl_elf)
5101618Srie 			(void) elf_end(ifl->ifl_elf);
5119131SRod.Evans@Sun.COM 	}
5121618Srie }
5130Sstevel@tonic-gate 
5141618Srie /*
5151618Srie  * Cleanup all memory that has been dynamically allocated during libld
5161618Srie  * processing and elf_end() all Elf descriptors that are still open.
5171618Srie  */
5181618Srie void
ld_ofl_cleanup(Ofl_desc * ofl)5191618Srie ld_ofl_cleanup(Ofl_desc *ofl)
5201618Srie {
5211618Srie 	Ld_heap		*chp, *php;
5221618Srie 	Ar_desc		*adp;
5239131SRod.Evans@Sun.COM 	Aliste		idx;
5241618Srie 
5259131SRod.Evans@Sun.COM 	ifl_list_cleanup(ofl->ofl_objs);
5269131SRod.Evans@Sun.COM 	ofl->ofl_objs = NULL;
5279131SRod.Evans@Sun.COM 	ifl_list_cleanup(ofl->ofl_sos);
5289131SRod.Evans@Sun.COM 	ofl->ofl_sos = NULL;
5290Sstevel@tonic-gate 
5309131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ofl->ofl_ars, idx, adp)) {
5311618Srie 		Ar_aux		*aup;
5321618Srie 		Elf_Arsym	*arsym;
5330Sstevel@tonic-gate 
5341618Srie 		for (arsym = adp->ad_start, aup = adp->ad_aux;
5351618Srie 		    arsym->as_name; ++arsym, ++aup) {
5361618Srie 			if ((aup->au_mem) && (aup->au_mem != FLG_ARMEM_PROC)) {
5371618Srie 				(void) elf_end(aup->au_mem->am_elf);
5381618Srie 
5391618Srie 				/*
5401618Srie 				 * Null out all entries to this member so
5411618Srie 				 * that we don't attempt to elf_end() it again.
5421618Srie 				 */
5431618Srie 				ld_ar_member(adp, arsym, aup, 0);
5440Sstevel@tonic-gate 			}
5450Sstevel@tonic-gate 		}
5461618Srie 		(void) elf_end(adp->ad_elf);
5471618Srie 	}
5489131SRod.Evans@Sun.COM 	ofl->ofl_ars = NULL;
5491618Srie 
5501618Srie 	(void) elf_end(ofl->ofl_elf);
5511618Srie 	(void) elf_end(ofl->ofl_welf);
5520Sstevel@tonic-gate 
5539131SRod.Evans@Sun.COM 	for (chp = ld_heap, php = NULL; chp; php = chp, chp = chp->lh_next) {
5541618Srie 		if (php)
5551618Srie 			(void) munmap((void *)php,
5561618Srie 			    (size_t)php->lh_end - (size_t)php);
5571618Srie 	}
5581618Srie 	if (php)
5591618Srie 		(void) munmap((void *)php, (size_t)php->lh_end - (size_t)php);
5601618Srie 
5619131SRod.Evans@Sun.COM 	ld_heap = NULL;
5620Sstevel@tonic-gate }
563