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