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