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 *
261007fd6fSAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27e912cc3dSJohn Levon *
28e912cc3dSJohn Levon * Copyright 2020 Joyent, Inc.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate /*
32ba2be530Sab196087 * Processing of relocatable objects and shared objects.
33ba2be530Sab196087 */
34ba2be530Sab196087
35ba2be530Sab196087 /*
367c478bd9Sstevel@tonic-gate * ld -- link/editor main program
377c478bd9Sstevel@tonic-gate */
385aefb655Srie #include <sys/types.h>
392017c965SRod Evans #include <sys/time.h>
405aefb655Srie #include <sys/mman.h>
417c478bd9Sstevel@tonic-gate #include <string.h>
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <locale.h>
447c478bd9Sstevel@tonic-gate #include <stdarg.h>
455aefb655Srie #include <debug.h>
467c478bd9Sstevel@tonic-gate #include "msg.h"
477c478bd9Sstevel@tonic-gate #include "_libld.h"
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*
50ba2be530Sab196087 * All target specific code is referenced via this global variable, which
51ba2be530Sab196087 * is initialized in ld_main(). This allows the linker to function as
52ba2be530Sab196087 * a cross linker, by vectoring to the target-specific code for the
53ba2be530Sab196087 * current target machine.
54ba2be530Sab196087 */
55ba2be530Sab196087 Target ld_targ;
56ba2be530Sab196087
57ba2be530Sab196087 /*
585aefb655Srie * A default library search path is used if one was not supplied on the command
595aefb655Srie * line. Note: these strings can not use MSG_ORIG() since they are modified as
605aefb655Srie * part of the path processing.
617c478bd9Sstevel@tonic-gate */
625aefb655Srie #if defined(_ELF64)
637c478bd9Sstevel@tonic-gate static char def_Plibpath[] = "/lib/64:/usr/lib/64";
647c478bd9Sstevel@tonic-gate #else
657c478bd9Sstevel@tonic-gate static char def_Plibpath[] = "/usr/ccs/lib:/lib:/usr/lib";
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate /*
695aefb655Srie * A default elf header provides for simplifying diagnostic processing.
705aefb655Srie */
715aefb655Srie static Ehdr def_ehdr = { { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
72ba2be530Sab196087 ELFCLASSNONE, ELFDATANONE }, 0, EM_NONE,
73ba2be530Sab196087 EV_CURRENT };
74ba2be530Sab196087
75ba2be530Sab196087 /*
761007fd6fSAli Bahrami * ld-centric wrapper on top of veprintf():
771007fd6fSAli Bahrami * - Accepts output descriptor rather than linkmap list
781007fd6fSAli Bahrami * - Sets the FLG_OF_FATAL/FLG_OF_WARN flags as necessary
791007fd6fSAli Bahrami */
801007fd6fSAli Bahrami void
ld_eprintf(Ofl_desc * ofl,Error error,const char * format,...)811007fd6fSAli Bahrami ld_eprintf(Ofl_desc *ofl, Error error, const char *format, ...)
821007fd6fSAli Bahrami {
831007fd6fSAli Bahrami va_list args;
841007fd6fSAli Bahrami
851007fd6fSAli Bahrami /* Set flag indicating type of error being issued */
861007fd6fSAli Bahrami switch (error) {
871007fd6fSAli Bahrami case ERR_NONE:
881007fd6fSAli Bahrami case ERR_WARNING_NF:
891007fd6fSAli Bahrami break;
901007fd6fSAli Bahrami case ERR_WARNING:
911007fd6fSAli Bahrami ofl->ofl_flags |= FLG_OF_WARN;
921007fd6fSAli Bahrami break;
931007fd6fSAli Bahrami case ERR_GUIDANCE:
941007fd6fSAli Bahrami ofl->ofl_guideflags |= FLG_OFG_ISSUED;
951007fd6fSAli Bahrami ofl->ofl_flags |= FLG_OF_WARN;
961007fd6fSAli Bahrami break;
971007fd6fSAli Bahrami default:
981007fd6fSAli Bahrami ofl->ofl_flags |= FLG_OF_FATAL;
991007fd6fSAli Bahrami }
1001007fd6fSAli Bahrami
1011007fd6fSAli Bahrami /* Issue the error */
1021007fd6fSAli Bahrami va_start(args, format);
1031007fd6fSAli Bahrami veprintf(ofl->ofl_lml, error, format, args);
1041007fd6fSAli Bahrami va_end(args);
1051007fd6fSAli Bahrami }
1061007fd6fSAli Bahrami
1071007fd6fSAli 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
ld_init_target(Lm_list * lml,Half mach)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
ld_main(int argc,char ** argv,Half mach)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;
1491007fd6fSAli 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 */
159*fb12490aSRichard Lowe if ((ofl = libld_calloc(1, sizeof (Ofl_desc))) == NULL)
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 */
178*fb12490aSRichard Lowe if ((ofl->ofl_sgsid = 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 */
1901007fd6fSAli Bahrami if (ld_process_flags(ofl, argc, argv) == S_ERROR) {
1911007fd6fSAli Bahrami /* If any ERR_GUIDANCE messages were issued, add a summary */
1921007fd6fSAli Bahrami if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
1931007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE,
1941007fd6fSAli Bahrami MSG_INTL(MSG_GUIDE_SUMMARY));
1957c478bd9Sstevel@tonic-gate return (1);
1961007fd6fSAli Bahrami }
1978222814eSRichard Lowe
1987c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_FATAL) {
1991007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FLAGS));
2001007fd6fSAli Bahrami /* If any ERR_GUIDANCE messages were issued, add a summary */
2011007fd6fSAli Bahrami if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
2021007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE,
2031007fd6fSAli Bahrami MSG_INTL(MSG_GUIDE_SUMMARY));
2047c478bd9Sstevel@tonic-gate return (1);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate * At this point a call such as ld -V is considered complete.
2097c478bd9Sstevel@tonic-gate */
2107c478bd9Sstevel@tonic-gate if (ofl->ofl_flags1 & FLG_OF1_DONE)
2117c478bd9Sstevel@tonic-gate return (0);
2127c478bd9Sstevel@tonic-gate
21356e2cc86SAli Bahrami /* Initialize signal handler */
21456e2cc86SAli Bahrami ld_init_sighandler(ofl);
21556e2cc86SAli Bahrami
2167c478bd9Sstevel@tonic-gate /*
217d2d5cf7cSAli Bahrami * Determine whether any support libraries should be loaded,
218d2d5cf7cSAli Bahrami * (either through the SGS_SUPPORT environment variable and/or
219d2d5cf7cSAli Bahrami * through the -S option).
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate #if defined(_LP64)
2227c478bd9Sstevel@tonic-gate if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_64))) == NULL)
2237c478bd9Sstevel@tonic-gate #else
2247c478bd9Sstevel@tonic-gate if ((sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT_32))) == NULL)
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate sgs_support = getenv(MSG_ORIG(MSG_SGS_SUPPORT));
2277c478bd9Sstevel@tonic-gate
22898c080d5SRod Evans if (sgs_support && sgs_support[0]) {
2297c478bd9Sstevel@tonic-gate const char *sep = MSG_ORIG(MSG_STR_COLON);
2307c478bd9Sstevel@tonic-gate char *lib;
2317c478bd9Sstevel@tonic-gate char *lasts;
2327c478bd9Sstevel@tonic-gate
2335aefb655Srie DBG_CALL(Dbg_support_req(ofl->ofl_lml, sgs_support,
2345aefb655Srie DBG_SUP_ENVIRON));
2357c478bd9Sstevel@tonic-gate if ((lib = strtok_r(sgs_support, sep, &lasts)) != NULL) {
2367c478bd9Sstevel@tonic-gate do {
2375aefb655Srie if (ld_sup_loadso(ofl, lib) == S_ERROR)
2385aefb655Srie return (ld_exit(ofl));
2392017c965SRod Evans DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate } while ((lib = strtok_r(NULL, sep, &lasts)) != NULL);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate }
24457ef7aa9SRod Evans if (lib_support) {
24557ef7aa9SRod Evans Aliste idx;
2467c478bd9Sstevel@tonic-gate char *lib;
2477c478bd9Sstevel@tonic-gate
24857ef7aa9SRod Evans for (APLIST_TRAVERSE(lib_support, idx, lib)) {
2495aefb655Srie DBG_CALL(Dbg_support_req(ofl->ofl_lml, lib,
2505aefb655Srie DBG_SUP_CMDLINE));
2515aefb655Srie if (ld_sup_loadso(ofl, lib) == S_ERROR)
2525aefb655Srie return (ld_exit(ofl));
2532926dd2eSrie DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
2542017c965SRod Evans }
2552017c965SRod Evans }
2567c478bd9Sstevel@tonic-gate
2574f680cc6SAli Bahrami DBG_CALL(Dbg_ent_print(ofl->ofl_lml,
2584f680cc6SAli Bahrami ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
25969112eddSAli Bahrami ofl->ofl_ents));
2604f680cc6SAli Bahrami DBG_CALL(Dbg_seg_list(ofl->ofl_lml,
2614f680cc6SAli Bahrami ofl->ofl_dehdr->e_ident[EI_OSABI], ofl->ofl_dehdr->e_machine,
26257ef7aa9SRod Evans ofl->ofl_segs));
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /*
2657c478bd9Sstevel@tonic-gate * The objscnt and soscnt variables were used to estimate the expected
2667c478bd9Sstevel@tonic-gate * input files, and size the symbol hash buckets accordingly. Reset
2677c478bd9Sstevel@tonic-gate * these values now, so as to gain an accurate count from pass two, for
2687c478bd9Sstevel@tonic-gate * later statistics diagnostics.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate ofl->ofl_objscnt = ofl->ofl_soscnt = 0;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * Determine whether we can create the file before going any further.
2747c478bd9Sstevel@tonic-gate */
2755aefb655Srie if (ld_open_outfile(ofl) == S_ERROR)
2765aefb655Srie return (ld_exit(ofl));
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate * If the user didn't supply a library path supply a default. And, if
2807c478bd9Sstevel@tonic-gate * no run-path has been specified (-R), see if the environment variable
281bb3b4f6cSRod Evans * is in use (historic).
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate if (Plibpath == NULL)
2847c478bd9Sstevel@tonic-gate Plibpath = def_Plibpath;
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate if (ofl->ofl_rpath == NULL) {
2877c478bd9Sstevel@tonic-gate char *rpath;
28898c080d5SRod Evans
2897c478bd9Sstevel@tonic-gate if (((rpath = getenv(MSG_ORIG(MSG_LD_RUN_PATH))) != NULL) &&
29098c080d5SRod Evans rpath[0])
2917c478bd9Sstevel@tonic-gate ofl->ofl_rpath = rpath;
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * Argument pass two. Input all libraries and objects.
2967c478bd9Sstevel@tonic-gate */
2975aefb655Srie if (ld_lib_setup(ofl) == S_ERROR)
2985aefb655Srie return (ld_exit(ofl));
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate /*
3017c478bd9Sstevel@tonic-gate * Call ld_start() with the etype of our output file and the
3027c478bd9Sstevel@tonic-gate * output file name.
3037c478bd9Sstevel@tonic-gate */
3047c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_SHAROBJ)
3057c478bd9Sstevel@tonic-gate etype = ET_DYN;
3067c478bd9Sstevel@tonic-gate else if (ofl->ofl_flags & FLG_OF_RELOBJ)
3077c478bd9Sstevel@tonic-gate etype = ET_REL;
3087c478bd9Sstevel@tonic-gate else
3097c478bd9Sstevel@tonic-gate etype = ET_EXEC;
3107c478bd9Sstevel@tonic-gate
3115aefb655Srie ld_sup_start(ofl, etype, argv[0]);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate * Process all input files.
3157c478bd9Sstevel@tonic-gate */
3165aefb655Srie if (ld_process_files(ofl, argc, argv) == S_ERROR)
3175aefb655Srie return (ld_exit(ofl));
3187c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_FATAL) {
3191007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_FILES),
3205aefb655Srie ofl->ofl_name);
3215aefb655Srie return (ld_exit(ofl));
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3245aefb655Srie ld_sup_input_done(ofl);
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate /*
32757ef7aa9SRod Evans * Now that all input section processing is complete, validate and
32857ef7aa9SRod Evans * process any SHT_SUNW_move sections.
3297c478bd9Sstevel@tonic-gate */
33057ef7aa9SRod Evans if (ofl->ofl_ismove && (ld_process_move(ofl) == S_ERROR))
3315aefb655Srie return (ld_exit(ofl));
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * Before validating all symbols count the number of relocation entries.
3357c478bd9Sstevel@tonic-gate * If copy relocations exist, COMMON symbols must be generated which are
3367c478bd9Sstevel@tonic-gate * assigned to the executables .bss. During sym_validate() the actual
3377c478bd9Sstevel@tonic-gate * size and alignment of the .bss is calculated. Doing things in this
3387c478bd9Sstevel@tonic-gate * order reduces the number of symbol table traversals required (however
3397c478bd9Sstevel@tonic-gate * it does take a little longer for the user to be told of any undefined
3407c478bd9Sstevel@tonic-gate * symbol errors).
3417c478bd9Sstevel@tonic-gate */
3425aefb655Srie if (ld_reloc_init(ofl) == S_ERROR)
3435aefb655Srie return (ld_exit(ofl));
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate /*
3461007fd6fSAli Bahrami * We need to know if FLG_OF_WARN is currently set, in case
3471007fd6fSAli Bahrami * we need to honor a -z fatal-warnings request. However, we also
3481007fd6fSAli Bahrami * need to know if a warning due to symbol validation results from
3491007fd6fSAli Bahrami * the upcoming call to ld_sym_validate() in order to issue the
3501007fd6fSAli Bahrami * appropriate message for it. So we save the current value,
3511007fd6fSAli Bahrami * and clear the main flag.
3521007fd6fSAli Bahrami */
3531007fd6fSAli Bahrami save_flg_of_warn = ofl->ofl_flags & FLG_OF_WARN;
3541007fd6fSAli Bahrami ofl->ofl_flags &= ~FLG_OF_WARN;
3551007fd6fSAli Bahrami
3561007fd6fSAli Bahrami if (ld_sym_validate(ofl) == S_ERROR)
3571007fd6fSAli Bahrami return (ld_exit(ofl));
3581007fd6fSAli Bahrami
3591007fd6fSAli Bahrami /*
3607c478bd9Sstevel@tonic-gate * Now that all symbol processing is complete see if any undefined
3617c478bd9Sstevel@tonic-gate * references still remain. If we observed undefined symbols the
3627c478bd9Sstevel@tonic-gate * FLG_OF_FATAL bit will be set: If creating a static executable, or a
3637c478bd9Sstevel@tonic-gate * dynamic executable or shared object with the -zdefs flag set, this
3647c478bd9Sstevel@tonic-gate * condition is fatal. If creating a shared object with the -Bsymbolic
3657c478bd9Sstevel@tonic-gate * flag set, this condition is simply a warning.
3667c478bd9Sstevel@tonic-gate */
3671007fd6fSAli Bahrami if (ofl->ofl_flags & FLG_OF_FATAL)
3681007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_SYM_FATAL),
3691007fd6fSAli Bahrami ofl->ofl_name);
3701007fd6fSAli Bahrami else if (ofl->ofl_flags & FLG_OF_WARN)
3711007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ARG_SYM_WARN));
3727c478bd9Sstevel@tonic-gate
3731007fd6fSAli Bahrami /*
3741007fd6fSAli Bahrami * Guidance: Use -z defs|nodefs when building shared objects.
3751007fd6fSAli Bahrami *
3761007fd6fSAli Bahrami * ld_sym_validate() will mask this guidance message out unless we are
3771007fd6fSAli Bahrami * intended to send it here, so all we need to do is use OFL_GUIDANCE()
3781007fd6fSAli Bahrami * to decide whether to issue it or not.
3791007fd6fSAli Bahrami */
3801007fd6fSAli Bahrami if (OFL_GUIDANCE(ofl, FLG_OFG_NO_DEFS))
3811007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_DEFS));
3821007fd6fSAli Bahrami
3831007fd6fSAli Bahrami /*
3841007fd6fSAli Bahrami * Symbol processing was the final step before we start producing the
3851007fd6fSAli Bahrami * output object. At this time, if we've seen warnings and the
3861007fd6fSAli Bahrami * -z fatal-warnings option is specified, promote them to fatal, which
3871007fd6fSAli Bahrami * will cause us to exit without creating an object.
3881007fd6fSAli Bahrami *
3891007fd6fSAli Bahrami * We didn't do this as the warnings were reported in order to
3901007fd6fSAli Bahrami * maximize the number of problems a given link-editor invocation
3911007fd6fSAli Bahrami * can diagnose. This is safe, since warnings are by definition events
3921007fd6fSAli Bahrami * one can choose to ignore.
3931007fd6fSAli Bahrami */
3941007fd6fSAli Bahrami if (((ofl->ofl_flags | save_flg_of_warn) &
3951007fd6fSAli Bahrami (FLG_OF_WARN | FLG_OF_FATWARN)) ==
3961007fd6fSAli Bahrami (FLG_OF_WARN | FLG_OF_FATWARN))
3971007fd6fSAli Bahrami ofl->ofl_flags |= FLG_OF_FATAL;
3981007fd6fSAli Bahrami
3991007fd6fSAli Bahrami /*
4001007fd6fSAli Bahrami * If fatal errors occurred in symbol processing, or due to warnings
4011007fd6fSAli Bahrami * promoted by -z fatal-warnings, this is the end of the line.
4021007fd6fSAli Bahrami */
4031007fd6fSAli Bahrami if (ofl->ofl_flags & FLG_OF_FATAL)
4045aefb655Srie return (ld_exit(ofl));
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * Generate any necessary sections.
4087c478bd9Sstevel@tonic-gate */
4095aefb655Srie if (ld_make_sections(ofl) == S_ERROR)
4105aefb655Srie return (ld_exit(ofl));
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /*
4130e233487SRod Evans * Now that all sections have been added to the output file, determine
4140e233487SRod Evans * whether any mapfile section ordering was specified, and verify that
4150e233487SRod Evans * all mapfile ordering directives have been matched. Issue a warning
4160e233487SRod Evans * for any directives that have not been matched.
4177c478bd9Sstevel@tonic-gate * Also, if SHF_ORDERED sections exist, set up sort key values.
4187c478bd9Sstevel@tonic-gate */
41969112eddSAli Bahrami if (ofl->ofl_flags & (FLG_OF_OS_ORDER | FLG_OF_KEY))
4205aefb655Srie ld_sec_validate(ofl);
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate * Having collected all the input data create the initial output file
4247c478bd9Sstevel@tonic-gate * image, assign virtual addresses to the image, and generate a load
4257c478bd9Sstevel@tonic-gate * map if the user requested one.
4267c478bd9Sstevel@tonic-gate */
4275aefb655Srie if (ld_create_outfile(ofl) == S_ERROR)
4285aefb655Srie return (ld_exit(ofl));
4297c478bd9Sstevel@tonic-gate
4305aefb655Srie if (ld_update_outfile(ofl) == S_ERROR)
4315aefb655Srie return (ld_exit(ofl));
4327c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_GENMAP)
4335aefb655Srie ld_map_out(ofl);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate * Build relocation sections and perform any relocation updates.
4377c478bd9Sstevel@tonic-gate */
4385aefb655Srie if (ld_reloc_process(ofl) == S_ERROR)
4395aefb655Srie return (ld_exit(ofl));
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate /*
4427e16fca0SAli Bahrami * Fill in contents for unwind header (.eh_frame_hdr)
4437c478bd9Sstevel@tonic-gate */
4447e16fca0SAli Bahrami if (ld_unwind_populate_hdr(ofl) == S_ERROR)
4455aefb655Srie return (ld_exit(ofl));
446ba2be530Sab196087
4477c478bd9Sstevel@tonic-gate /*
4487c478bd9Sstevel@tonic-gate * Finally create the files elf checksum.
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate if (ofl->ofl_checksum)
4517c478bd9Sstevel@tonic-gate *ofl->ofl_checksum = (Xword)elf_checksum(ofl->ofl_elf);
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate /*
454ba2be530Sab196087 * If this is a cross link to a target with a different byte
455ba2be530Sab196087 * order than the linker, swap the data to the target byte order.
456ba2be530Sab196087 */
457ba2be530Sab196087 if (((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) &&
458ba2be530Sab196087 (_elf_swap_wrimage(ofl->ofl_elf) != 0)) {
4591007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_SWAP_WRIMAGE),
460ba2be530Sab196087 ofl->ofl_name);
461ba2be530Sab196087 return (ld_exit(ofl));
462ba2be530Sab196087 }
463ba2be530Sab196087
464ba2be530Sab196087 /*
4657c478bd9Sstevel@tonic-gate * We're done, so make sure the updates are flushed to the output file.
4667c478bd9Sstevel@tonic-gate */
4677c478bd9Sstevel@tonic-gate if ((ofl->ofl_size = elf_update(ofl->ofl_welf, ELF_C_WRITE)) == 0) {
4681007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_UPDATE),
4695aefb655Srie ofl->ofl_name);
4705aefb655Srie return (ld_exit(ofl));
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate
4735aefb655Srie ld_sup_atexit(ofl, 0);
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_statistics_ld(ofl));
4762017c965SRod Evans DBG_CALL(Dbg_basic_finish(ofl->ofl_lml));
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
479e23c41c9SAli Bahrami * Wrap up debug output file if one is open
480e23c41c9SAli Bahrami */
481e23c41c9SAli Bahrami dbg_cleanup();
482e23c41c9SAli Bahrami
4831007fd6fSAli Bahrami /* If any ERR_GUIDANCE messages were issued, add a summary */
484e912cc3dSJohn Levon if (ofl->ofl_guideflags & FLG_OFG_ISSUED) {
4851007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_SUMMARY));
486e912cc3dSJohn Levon ofl->ofl_guideflags &= ~FLG_OFG_ISSUED;
487e912cc3dSJohn Levon }
488e912cc3dSJohn Levon
489e912cc3dSJohn Levon /*
490e912cc3dSJohn Levon * One final check for any new warnings we found that should fail the
491e912cc3dSJohn Levon * link edit.
492e912cc3dSJohn Levon */
493e912cc3dSJohn Levon if ((ofl->ofl_flags & (FLG_OF_WARN | FLG_OF_FATWARN)) ==
494e912cc3dSJohn Levon (FLG_OF_WARN | FLG_OF_FATWARN))
495e912cc3dSJohn Levon return (ld_exit(ofl));
4961007fd6fSAli Bahrami
497e23c41c9SAli Bahrami /*
498*fb12490aSRichard Lowe * For performance reasons we didn't used to actually free up the
499*fb12490aSRichard Lowe * memory we'd allocated, since it'll be freed on exit.
5007c478bd9Sstevel@tonic-gate *
501*fb12490aSRichard Lowe * These calls does not free nearly as much memory as you would think
502*fb12490aSRichard Lowe * they do, unfortunately.
5037c478bd9Sstevel@tonic-gate */
504*fb12490aSRichard Lowe ld_ofl_cleanup(ofl);
505*fb12490aSRichard Lowe libld_free(ofl);
5067c478bd9Sstevel@tonic-gate return (0);
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate
5095aefb655Srie /*
5105aefb655Srie * Cleanup an Ifl_desc.
5115aefb655Srie */
5125aefb655Srie static void
ifl_list_cleanup(APlist * apl)51357ef7aa9SRod Evans ifl_list_cleanup(APlist *apl)
5147c478bd9Sstevel@tonic-gate {
51557ef7aa9SRod Evans Aliste idx;
5165aefb655Srie Ifl_desc *ifl;
5177c478bd9Sstevel@tonic-gate
51857ef7aa9SRod Evans for (APLIST_TRAVERSE(apl, idx, ifl)) {
5195aefb655Srie if (ifl->ifl_elf)
5205aefb655Srie (void) elf_end(ifl->ifl_elf);
52157ef7aa9SRod Evans }
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate /*
5255aefb655Srie * Cleanup all memory that has been dynamically allocated during libld
5265aefb655Srie * processing and elf_end() all Elf descriptors that are still open.
5277c478bd9Sstevel@tonic-gate */
5285aefb655Srie void
ld_ofl_cleanup(Ofl_desc * ofl)5295aefb655Srie ld_ofl_cleanup(Ofl_desc *ofl)
5305aefb655Srie {
5315aefb655Srie Ar_desc *adp;
53257ef7aa9SRod Evans Aliste idx;
5337c478bd9Sstevel@tonic-gate
53457ef7aa9SRod Evans ifl_list_cleanup(ofl->ofl_objs);
53557ef7aa9SRod Evans ofl->ofl_objs = NULL;
53657ef7aa9SRod Evans ifl_list_cleanup(ofl->ofl_sos);
53757ef7aa9SRod Evans ofl->ofl_sos = NULL;
5385aefb655Srie
53957ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_ars, idx, adp)) {
5405aefb655Srie Ar_aux *aup;
5415aefb655Srie Elf_Arsym *arsym;
5425aefb655Srie
543b3403853SRichard Lowe /*
544b3403853SRichard Lowe * Free up member information for normally processed archives.
545b3403853SRichard Lowe * Archives processed under -z allextract have no member
546b3403853SRichard Lowe * information or symbol table, and members have already been
547b3403853SRichard Lowe * dealt with as input files.
548b3403853SRichard Lowe */
549b3403853SRichard Lowe if (adp->ad_allextract == TRUE)
550b3403853SRichard Lowe continue;
551b3403853SRichard Lowe
5525aefb655Srie for (arsym = adp->ad_start, aup = adp->ad_aux;
553b3403853SRichard Lowe (arsym->as_name != NULL); ++arsym, ++aup) {
554b3403853SRichard Lowe if ((aup->au_mem != NULL) &&
555b3403853SRichard Lowe (aup->au_mem != FLG_ARMEM_PROC)) {
5565aefb655Srie (void) elf_end(aup->au_mem->am_elf);
5575aefb655Srie
5585aefb655Srie /*
5595aefb655Srie * Null out all entries to this member so
5605aefb655Srie * that we don't attempt to elf_end() it again.
5615aefb655Srie */
5625aefb655Srie ld_ar_member(adp, arsym, aup, 0);
5635aefb655Srie }
5645aefb655Srie }
5655aefb655Srie (void) elf_end(adp->ad_elf);
5665aefb655Srie }
56757ef7aa9SRod Evans ofl->ofl_ars = NULL;
5685aefb655Srie
5695aefb655Srie (void) elf_end(ofl->ofl_elf);
5705aefb655Srie (void) elf_end(ofl->ofl_welf);
5715aefb655Srie
572*fb12490aSRichard Lowe /*
573*fb12490aSRichard Lowe * Note that we don't free ofl itself here, just its contents. The
574*fb12490aSRichard Lowe * ofl itself belongs to the caller.
575*fb12490aSRichard Lowe */
5767c478bd9Sstevel@tonic-gate }
577