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. 27c8937b0dSRichard Lowe * 28c8937b0dSRichard Lowe * Copyright 2011, Richard Lowe. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * This file contains the functions responsible for opening the output file 337c478bd9Sstevel@tonic-gate * image, associating the appropriate input elf structures with the new image, 347c478bd9Sstevel@tonic-gate * and obtaining new elf structures to define the new image. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate #include <stdio.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include <link.h> 407c478bd9Sstevel@tonic-gate #include <errno.h> 417c478bd9Sstevel@tonic-gate #include <string.h> 427c478bd9Sstevel@tonic-gate #include <limits.h> 435aefb655Srie #include <debug.h> 4413246550Sab196087 #include <unistd.h> 457c478bd9Sstevel@tonic-gate #include "msg.h" 467c478bd9Sstevel@tonic-gate #include "_libld.h" 475aefb655Srie 485aefb655Srie /* 495aefb655Srie * Determine a least common multiplier. Input sections contain an alignment 505aefb655Srie * requirement, which elf_update() uses to insure that the section is aligned 515aefb655Srie * correctly off of the base of the elf image. We must also insure that the 525aefb655Srie * sections mapping is congruent with this alignment requirement. For each 535aefb655Srie * input section associated with a loadable segment determine whether the 545aefb655Srie * segments alignment must be adjusted to compensate for a sections alignment 555aefb655Srie * requirements. 565aefb655Srie */ 575aefb655Srie Xword 585aefb655Srie ld_lcm(Xword a, Xword b) 595aefb655Srie { 605aefb655Srie Xword _r, _a, _b; 615aefb655Srie 625aefb655Srie if ((_a = a) == 0) 635aefb655Srie return (b); 645aefb655Srie if ((_b = b) == 0) 655aefb655Srie return (a); 665aefb655Srie 675aefb655Srie if (_a > _b) 685aefb655Srie _a = b, _b = a; 695aefb655Srie while ((_r = _b % _a) != 0) 705aefb655Srie _b = _a, _a = _r; 715aefb655Srie return ((a / _a) * b); 725aefb655Srie } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * Open the output file and insure the correct access modes. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate uintptr_t 785aefb655Srie ld_open_outfile(Ofl_desc * ofl) 797c478bd9Sstevel@tonic-gate { 8013246550Sab196087 mode_t mode; 817c478bd9Sstevel@tonic-gate struct stat status; 8213246550Sab196087 830f5dca20Sab196087 /* 840f5dca20Sab196087 * Determine the required file mode from the type of output file we 850f5dca20Sab196087 * are creating. 860f5dca20Sab196087 */ 870f5dca20Sab196087 mode = (ofl->ofl_flags & (FLG_OF_EXEC | FLG_OF_SHAROBJ)) 880f5dca20Sab196087 ? 0777 : 0666; 890f5dca20Sab196087 9013246550Sab196087 /* Determine if the output file already exists */ 9113246550Sab196087 if (stat(ofl->ofl_name, &status) == 0) { 9213246550Sab196087 if ((status.st_mode & S_IFMT) != S_IFREG) { 9313246550Sab196087 /* 9413246550Sab196087 * It is not a regular file, so don't delete it 9513246550Sab196087 * or allow it to be deleted. This allows root 9613246550Sab196087 * users to specify /dev/null output file for 9713246550Sab196087 * verification links. 9813246550Sab196087 */ 9913246550Sab196087 ofl->ofl_flags1 |= FLG_OF1_NONREG; 10013246550Sab196087 } else { 10113246550Sab196087 /* 10213246550Sab196087 * It's a regular file, so unlink it. In standard 10313246550Sab196087 * Unix fashion, the old file will continue to 10413246550Sab196087 * exist until its link count drops to 0 and no 10513246550Sab196087 * process has the file open. In the meantime, we 10613246550Sab196087 * create a new file (inode) under the same name, 10713246550Sab196087 * available for new use. 10813246550Sab196087 * 10913246550Sab196087 * The advantage of this policy is that creating 11013246550Sab196087 * a new executable or sharable library does not 11113246550Sab196087 * corrupt existing processes using the old file. 11213246550Sab196087 * A possible disadvantage is that if the existing 11313246550Sab196087 * file has a (link_count > 1), the other names will 11413246550Sab196087 * continue to reference the old inode, thus 11513246550Sab196087 * breaking the link. 1160f5dca20Sab196087 * 1170f5dca20Sab196087 * A subtlety here is that POSIX says we are not 1180f5dca20Sab196087 * supposed to replace a non-writable file, which 1190f5dca20Sab196087 * is something that unlink() is happy to do. The 1200f5dca20Sab196087 * only 100% reliable test against this is to open 1210f5dca20Sab196087 * the file for non-destructive write access. If the 1220f5dca20Sab196087 * open succeeds, we are clear to unlink it, and if 1230f5dca20Sab196087 * not, then the error generated is the error we 1240f5dca20Sab196087 * need to report. 12513246550Sab196087 */ 1260f5dca20Sab196087 if ((ofl->ofl_fd = open(ofl->ofl_name, O_RDWR, 1270f5dca20Sab196087 mode)) < 0) { 1280f5dca20Sab196087 int err = errno; 1290f5dca20Sab196087 1300f5dca20Sab196087 if (err != ENOENT) { 1311007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 1320f5dca20Sab196087 MSG_INTL(MSG_SYS_OPEN), 1330f5dca20Sab196087 ofl->ofl_name, strerror(err)); 1340f5dca20Sab196087 return (S_ERROR); 1350f5dca20Sab196087 } 1360f5dca20Sab196087 } else { 1370f5dca20Sab196087 (void) close(ofl->ofl_fd); 1380f5dca20Sab196087 } 1390f5dca20Sab196087 14013246550Sab196087 if ((unlink(ofl->ofl_name) == -1) && 14113246550Sab196087 (errno != ENOENT)) { 14213246550Sab196087 int err = errno; 14313246550Sab196087 1441007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 14513246550Sab196087 MSG_INTL(MSG_SYS_UNLINK), 14613246550Sab196087 ofl->ofl_name, strerror(err)); 14713246550Sab196087 return (S_ERROR); 14813246550Sab196087 } 14913246550Sab196087 } 15013246550Sab196087 } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * Open (or create) the output file name (ofl_fd acts as a global 1547c478bd9Sstevel@tonic-gate * flag to ldexit() signifying whether the output file should be 1557c478bd9Sstevel@tonic-gate * removed or not on error). 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate if ((ofl->ofl_fd = open(ofl->ofl_name, O_RDWR | O_CREAT | O_TRUNC, 1587c478bd9Sstevel@tonic-gate mode)) < 0) { 1597c478bd9Sstevel@tonic-gate int err = errno; 1607c478bd9Sstevel@tonic-gate 1611007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), 1625aefb655Srie ofl->ofl_name, strerror(err)); 1637c478bd9Sstevel@tonic-gate return (S_ERROR); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate return (1); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * If we are creating a memory model we need to update the present memory image. 172635216b6SRod Evans * Use elf_update(ELF_C_NULL) to calculate the offset of each section and their 173635216b6SRod Evans * associated data buffers. From this information determine what padding is 174635216b6SRod Evans * required. 175635216b6SRod Evans * 1767c478bd9Sstevel@tonic-gate * Two actions are necessary to convert the present disc image into a memory 1777c478bd9Sstevel@tonic-gate * image: 1787c478bd9Sstevel@tonic-gate * 179635216b6SRod Evans * - Loadable segments must be padded so that the next segment virtual 1807c478bd9Sstevel@tonic-gate * address and file offset are the same. 1817c478bd9Sstevel@tonic-gate * 182635216b6SRod Evans * - NOBITS sections must be converted into allocated, null filled sections. 1837c478bd9Sstevel@tonic-gate */ 1845aefb655Srie static uintptr_t 1857c478bd9Sstevel@tonic-gate pad_outfile(Ofl_desc *ofl) 1867c478bd9Sstevel@tonic-gate { 18757ef7aa9SRod Evans Aliste idx1; 1887c478bd9Sstevel@tonic-gate off_t offset; 1897c478bd9Sstevel@tonic-gate Elf_Scn *oscn = 0; 1907c478bd9Sstevel@tonic-gate Sg_desc *sgp; 1917c478bd9Sstevel@tonic-gate Ehdr *ehdr; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * Update all the elf structures. This will assign offsets to the 1957c478bd9Sstevel@tonic-gate * section headers and data buffers as they relate to the new image. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate if (elf_update(ofl->ofl_welf, ELF_C_NULL) == -1) { 1981007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_UPDATE), 1995aefb655Srie ofl->ofl_name); 2007c478bd9Sstevel@tonic-gate return (S_ERROR); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate if ((ehdr = elf_getehdr(ofl->ofl_welf)) == NULL) { 2031007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETEHDR), 2045aefb655Srie ofl->ofl_name); 2057c478bd9Sstevel@tonic-gate return (S_ERROR); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Initialize the offset by skipping the Elf header and program 2107c478bd9Sstevel@tonic-gate * headers. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate offset = ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Traverse the segment list looking for loadable segments. 2167c478bd9Sstevel@tonic-gate */ 21757ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 2187c478bd9Sstevel@tonic-gate Phdr *phdr = &(sgp->sg_phdr); 219cce0e03bSab196087 Os_desc *osp; 22057ef7aa9SRod Evans Aliste idx2; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * If we've already processed a loadable segment, the `scn' 2247c478bd9Sstevel@tonic-gate * variable will be initialized to the last section that was 2257c478bd9Sstevel@tonic-gate * part of that segment. Add sufficient padding to this section 2267c478bd9Sstevel@tonic-gate * to cause the next segments virtual address and file offset to 2277c478bd9Sstevel@tonic-gate * be the same. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate if (oscn && (phdr->p_type == PT_LOAD)) { 2307c478bd9Sstevel@tonic-gate Elf_Data * data; 2317c478bd9Sstevel@tonic-gate size_t size; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate size = (size_t)(S_ROUND(offset, phdr->p_align) - 2347c478bd9Sstevel@tonic-gate offset); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if ((data = elf_newdata(oscn)) == NULL) { 2371007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 2385aefb655Srie MSG_INTL(MSG_ELF_NEWDATA), ofl->ofl_name); 2397c478bd9Sstevel@tonic-gate return (S_ERROR); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate if ((data->d_buf = libld_calloc(size, 1)) == 0) 2427c478bd9Sstevel@tonic-gate return (S_ERROR); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate data->d_type = ELF_T_BYTE; 2457c478bd9Sstevel@tonic-gate data->d_size = size; 2467c478bd9Sstevel@tonic-gate data->d_align = 1; 2475aefb655Srie data->d_version = ofl->ofl_dehdr->e_version; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Traverse the output sections for this segment calculating the 2527c478bd9Sstevel@tonic-gate * offset of each section. Retain the final section descriptor 2537c478bd9Sstevel@tonic-gate * as this will be where any padding buffer will be added. 2547c478bd9Sstevel@tonic-gate */ 25557ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 256cce0e03bSab196087 Shdr *shdr = osp->os_shdr; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate offset = (off_t)S_ROUND(offset, shdr->sh_addralign); 2597c478bd9Sstevel@tonic-gate offset += shdr->sh_size; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * If this is a NOBITS output section convert all of 2637c478bd9Sstevel@tonic-gate * its associated input sections into real, null filled, 2647c478bd9Sstevel@tonic-gate * data buffers, and change the section to PROGBITS. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_NOBITS) 2677c478bd9Sstevel@tonic-gate shdr->sh_type = SHT_PROGBITS; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * If this is a loadable segment retain the last output section 2727c478bd9Sstevel@tonic-gate * descriptor. This acts both as a flag that a loadable 2737c478bd9Sstevel@tonic-gate * segment has been seen, and as the segment to which a padding 2747c478bd9Sstevel@tonic-gate * buffer will be added. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_LOAD) 2777c478bd9Sstevel@tonic-gate oscn = osp->os_scn; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate return (1); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* 28312b8e62eSrie * Create an output section. The first instance of an input section triggers 28412b8e62eSrie * the creation of a new output section. 28512b8e62eSrie */ 28612b8e62eSrie static uintptr_t 28712b8e62eSrie create_outsec(Ofl_desc *ofl, Sg_desc *sgp, Os_desc *osp, Word ptype, int shidx, 28812b8e62eSrie Boolean fixalign) 28912b8e62eSrie { 29012b8e62eSrie Elf_Scn *scn; 29112b8e62eSrie Shdr *shdr; 29212b8e62eSrie 29312b8e62eSrie /* 29412b8e62eSrie * Get a section descriptor for the section. 29512b8e62eSrie */ 29612b8e62eSrie if ((scn = elf_newscn(ofl->ofl_welf)) == NULL) { 2971007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_NEWSCN), 29812b8e62eSrie ofl->ofl_name); 29912b8e62eSrie return (S_ERROR); 30012b8e62eSrie } 30112b8e62eSrie osp->os_scn = scn; 30212b8e62eSrie 30312b8e62eSrie /* 30412b8e62eSrie * Get a new section header table entry and copy the pertinent 30512b8e62eSrie * information from the in-core descriptor. 30612b8e62eSrie */ 30712b8e62eSrie if ((shdr = elf_getshdr(scn)) == NULL) { 3081007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSHDR), 30912b8e62eSrie ofl->ofl_name); 31012b8e62eSrie return (S_ERROR); 31112b8e62eSrie } 31212b8e62eSrie *shdr = *(osp->os_shdr); 31312b8e62eSrie osp->os_shdr = shdr; 31412b8e62eSrie 31512b8e62eSrie /* 31612b8e62eSrie * If this is the first section within a loadable segment, and the 31712b8e62eSrie * alignment needs to be updated, record this section. 31812b8e62eSrie */ 31912b8e62eSrie if ((fixalign == TRUE) && (ptype == PT_LOAD) && (shidx == 1)) 32012b8e62eSrie sgp->sg_fscn = scn; 32112b8e62eSrie 32212b8e62eSrie /* 3239ffca373SAli Bahrami * If not building a relocatable object, remove any of the 3249ffca373SAli Bahrami * following flags, as they have been acted upon and are not 3259ffca373SAli Bahrami * meaningful in the output: 3269ffca373SAli Bahrami * SHF_ORDERED, SHF_LINK_ORDER, SHF_GROUP 3279ffca373SAli Bahrami * For relocatable objects, we allow them to propagate to 3289ffca373SAli Bahrami * the output object to be handled by the next linker that 3299ffca373SAli Bahrami * sees them. 33012b8e62eSrie */ 33112b8e62eSrie if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) 3329ffca373SAli Bahrami osp->os_shdr->sh_flags &= ~(ALL_SHF_ORDER|SHF_GROUP); 33312b8e62eSrie 33412b8e62eSrie /* 33512b8e62eSrie * If this is a TLS section, save it so that the PT_TLS program header 33612b8e62eSrie * information can be established after the output image has been 33712b8e62eSrie * initially created. At this point, all TLS input sections are ordered 33812b8e62eSrie * as they will appear in the output image. 33912b8e62eSrie */ 34012b8e62eSrie if ((ofl->ofl_flags & FLG_OF_TLSPHDR) && 34112b8e62eSrie (osp->os_shdr->sh_flags & SHF_TLS) && 34257ef7aa9SRod Evans (aplist_append(&ofl->ofl_ostlsseg, osp, 34357ef7aa9SRod Evans AL_CNT_OFL_OSTLSSEG) == NULL)) 34412b8e62eSrie return (S_ERROR); 34512b8e62eSrie 34612b8e62eSrie return (0); 34712b8e62eSrie } 34812b8e62eSrie 34912b8e62eSrie /* 3507c478bd9Sstevel@tonic-gate * Create the elf structures that allow the input data to be associated with the 3517c478bd9Sstevel@tonic-gate * new image: 3527c478bd9Sstevel@tonic-gate * 353635216b6SRod Evans * - define the new elf image using elf_begin(), 3547c478bd9Sstevel@tonic-gate * 355635216b6SRod Evans * - obtain an elf header for the image, 3567c478bd9Sstevel@tonic-gate * 357635216b6SRod Evans * - traverse the input segments and create a program header array to define 358635216b6SRod Evans * the required segments, 3597c478bd9Sstevel@tonic-gate * 360635216b6SRod Evans * - traverse the output sections for each segment assigning a new section 361635216b6SRod Evans * descriptor and section header for each, 3627c478bd9Sstevel@tonic-gate * 363635216b6SRod Evans * - traverse the input sections associated with each output section and 364635216b6SRod Evans * assign a new data descriptor to each (each output section becomes a 365635216b6SRod Evans * linked list of input data buffers). 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate uintptr_t 3685aefb655Srie ld_create_outfile(Ofl_desc *ofl) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate Sg_desc *sgp; 371cce0e03bSab196087 Os_desc *osp; 3727c478bd9Sstevel@tonic-gate Is_desc *isp; 373dd94ecefSrie Elf_Data *tlsdata = 0; 37457ef7aa9SRod Evans Aliste idx1; 3751d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 3761d9df23bSab196087 ofl_flag_t flags1 = ofl->ofl_flags1; 37757ef7aa9SRod Evans size_t ndx; 3787c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 3797c478bd9Sstevel@tonic-gate Boolean fixalign = FALSE; 38057ef7aa9SRod Evans int fd, nseg = 0, shidx, dataidx, ptloadidx = 0; 3817c478bd9Sstevel@tonic-gate 3822017c965SRod Evans DBG_CALL(Dbg_basic_create(ofl->ofl_lml)); 3832017c965SRod Evans 3847c478bd9Sstevel@tonic-gate /* 38569112eddSAli Bahrami * If DF_1_NOHDR or FLG_OF1_VADDR were set, 3867c478bd9Sstevel@tonic-gate * we need to do alignment adjustment. 3877c478bd9Sstevel@tonic-gate */ 3889039eeafSab196087 if ((flags1 & FLG_OF1_VADDR) || 3894899432aSab196087 (ofl->ofl_dtflags_1 & DF_1_NOHDR)) { 3907c478bd9Sstevel@tonic-gate fixalign = TRUE; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3939039eeafSab196087 if (flags1 & FLG_OF1_MEMORY) { 3947c478bd9Sstevel@tonic-gate cmd = ELF_C_IMAGE; 3957c478bd9Sstevel@tonic-gate fd = 0; 3967c478bd9Sstevel@tonic-gate } else { 3977c478bd9Sstevel@tonic-gate fd = ofl->ofl_fd; 3987c478bd9Sstevel@tonic-gate cmd = ELF_C_WRITE; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027010c12aSrie * If there are any ordered sections, handle them here. 4037c478bd9Sstevel@tonic-gate */ 40457ef7aa9SRod Evans if ((ofl->ofl_ordered != NULL) && 4055aefb655Srie (ld_sort_ordered(ofl) == S_ERROR)) 4067c478bd9Sstevel@tonic-gate return (S_ERROR); 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Tell the access library about our new temporary file. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate if ((ofl->ofl_welf = elf_begin(fd, cmd, 0)) == NULL) { 4121007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_BEGIN), 4135aefb655Srie ofl->ofl_name); 4147c478bd9Sstevel@tonic-gate return (S_ERROR); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * Obtain a new Elf header. 4197c478bd9Sstevel@tonic-gate */ 4205aefb655Srie if ((ofl->ofl_nehdr = elf_newehdr(ofl->ofl_welf)) == NULL) { 4211007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_NEWEHDR), 4225aefb655Srie ofl->ofl_name); 4237c478bd9Sstevel@tonic-gate return (S_ERROR); 4247c478bd9Sstevel@tonic-gate } 4255aefb655Srie ofl->ofl_nehdr->e_machine = ofl->ofl_dehdr->e_machine; 4267c478bd9Sstevel@tonic-gate 4275aefb655Srie DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD)); 42857ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 429dd94ecefSrie int frst = 0; 430dd94ecefSrie Phdr *phdr = &(sgp->sg_phdr); 431dd94ecefSrie Word ptype = phdr->p_type; 43257ef7aa9SRod Evans Aliste idx2; 433c8937b0dSRichard Lowe Os_desc *nonempty = NULL; /* First non-empty section */ 434dd94ecefSrie 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * Count the number of segments that will go in the program 4377c478bd9Sstevel@tonic-gate * header table. If a segment is empty, ignore it. 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) { 4404f680cc6SAli Bahrami /* 4414f680cc6SAli Bahrami * If the program header type belongs to the os range, 4424f680cc6SAli Bahrami * the resulting object is ELFOSABI_SOLARIS. 4434f680cc6SAli Bahrami */ 4444f680cc6SAli Bahrami if ((ptype >= PT_LOOS) && (ptype <= PT_HIOS)) 4454f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI; 4464f680cc6SAli Bahrami 4477c478bd9Sstevel@tonic-gate if (ptype == PT_PHDR) { 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * If we are generating an interp section (and 4507c478bd9Sstevel@tonic-gate * thus an associated PT_INTERP program header 4517c478bd9Sstevel@tonic-gate * entry) also generate a PT_PHDR program header 4527c478bd9Sstevel@tonic-gate * entry. This allows the kernel to generate 4537c478bd9Sstevel@tonic-gate * the appropriate aux vector entries to pass to 4547c478bd9Sstevel@tonic-gate * the interpreter (refer to exec/elf/elf.c). 4557c478bd9Sstevel@tonic-gate * Note that if an image was generated with an 4567c478bd9Sstevel@tonic-gate * interp section, but no associated PT_PHDR 4577c478bd9Sstevel@tonic-gate * program header entry, the kernel will simply 4587c478bd9Sstevel@tonic-gate * pass the interpreter an open file descriptor 4597c478bd9Sstevel@tonic-gate * when the image is executed). 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) 4627c478bd9Sstevel@tonic-gate nseg++; 4637c478bd9Sstevel@tonic-gate } else if (ptype == PT_INTERP) { 4647c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) 4657c478bd9Sstevel@tonic-gate nseg++; 4667c478bd9Sstevel@tonic-gate } else if (ptype == PT_DYNAMIC) { 4677c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) 4687c478bd9Sstevel@tonic-gate nseg++; 4697c478bd9Sstevel@tonic-gate } else if (ptype == PT_TLS) { 470dd94ecefSrie if (flags & FLG_OF_TLSPHDR) 4717c478bd9Sstevel@tonic-gate nseg++; 4727e16fca0SAli Bahrami } else if (ptype == PT_SUNW_UNWIND) { 4737c478bd9Sstevel@tonic-gate if (ofl->ofl_unwindhdr) 4747c478bd9Sstevel@tonic-gate nseg++; 4757c478bd9Sstevel@tonic-gate } else if (ptype == PT_SUNWDTRACE) { 4767c478bd9Sstevel@tonic-gate if (ofl->ofl_dtracesym) 4777c478bd9Sstevel@tonic-gate nseg++; 4787c478bd9Sstevel@tonic-gate } else if (ptype == PT_SUNWCAP) { 4797c478bd9Sstevel@tonic-gate if (ofl->ofl_oscap) 4807c478bd9Sstevel@tonic-gate nseg++; 48169112eddSAli Bahrami } else if (ptype == PT_SUNWSTACK) { 48269112eddSAli Bahrami if ((sgp->sg_flags & FLG_SG_DISABLED) == 0) 48369112eddSAli Bahrami nseg++; 484d1827f25Srie } else if (sgp->sg_flags & FLG_SG_EMPTY) { 485d1827f25Srie nseg++; 486d1827f25Srie } else if (sgp->sg_osdescs != NULL) { 487d1827f25Srie if ((sgp->sg_flags & FLG_SG_PHREQ) == 0) { 48854d82594Sseizo /* 48954d82594Sseizo * If this is a segment for which 49054d82594Sseizo * we are not making a program header, 49154d82594Sseizo * don't increment nseg 49254d82594Sseizo */ 49354d82594Sseizo ptype = (sgp->sg_phdr).p_type = PT_NULL; 49454d82594Sseizo } else if (ptype != PT_NULL) 4957c478bd9Sstevel@tonic-gate nseg++; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 500bb3b4f6cSRod Evans * Establish any processing unique to the first loadable 501bb3b4f6cSRod Evans * segment. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate if ((ptype == PT_LOAD) && (ptloadidx == 0)) { 5047c478bd9Sstevel@tonic-gate ptloadidx++; 505bb3b4f6cSRod Evans 506bb3b4f6cSRod Evans /* 50769112eddSAli Bahrami * If the first loadable segment is not supposed to 50869112eddSAli Bahrami * include the ELF or program headers, alignments 50969112eddSAli Bahrami * of the following segments need to be fixed, 510bb3b4f6cSRod Evans * plus a .dynamic FLAGS1 setting is required. 511bb3b4f6cSRod Evans */ 51269112eddSAli Bahrami if (ofl->ofl_dtflags_1 & DF_1_NOHDR) 5137c478bd9Sstevel@tonic-gate fixalign = TRUE; 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate shidx = 0; 51757ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 51857ef7aa9SRod Evans Aliste idx3; 5191dd9d86fSAli Bahrami int os_isdescs_idx; 5200bc07c75Srie 5217c478bd9Sstevel@tonic-gate dataidx = 0; 5221dd9d86fSAli Bahrami 5231dd9d86fSAli Bahrami OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) { 5247c478bd9Sstevel@tonic-gate Elf_Data *data; 5257c478bd9Sstevel@tonic-gate Ifl_desc *ifl = isp->is_file; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 528d2ef9fe9Sab196087 * An input section in the list that has 529d2ef9fe9Sab196087 * been previously marked to be discarded 530d2ef9fe9Sab196087 * should be completely ignored. 531d2ef9fe9Sab196087 */ 532d2ef9fe9Sab196087 if (isp->is_flags & FLG_IS_DISCARD) 533d2ef9fe9Sab196087 continue; 534d2ef9fe9Sab196087 535d2ef9fe9Sab196087 /* 5367c478bd9Sstevel@tonic-gate * At this point we know whether a section has 5377c478bd9Sstevel@tonic-gate * been referenced. If it hasn't, and the whole 5387c478bd9Sstevel@tonic-gate * file hasn't been referenced (which would have 5397c478bd9Sstevel@tonic-gate * been caught in ignore_section_processing()), 5407c478bd9Sstevel@tonic-gate * give a diagnostic (-D unused,detail) or 5417c478bd9Sstevel@tonic-gate * discard the section if -zignore is in effect. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate if (ifl && 5447c478bd9Sstevel@tonic-gate (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) || 5457c478bd9Sstevel@tonic-gate ((ptype == PT_LOAD) && 5467c478bd9Sstevel@tonic-gate ((isp->is_flags & FLG_IS_SECTREF) == 0) && 5477c478bd9Sstevel@tonic-gate (isp->is_shdr->sh_size > 0)))) { 5485aefb655Srie Lm_list *lml = ofl->ofl_lml; 5495aefb655Srie 5507c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_IGNORE) { 5517c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_DISCARD; 552cce0e03bSab196087 DBG_CALL(Dbg_unused_sec(lml, 553cce0e03bSab196087 isp)); 5547c478bd9Sstevel@tonic-gate continue; 555cce0e03bSab196087 } else { 556cce0e03bSab196087 DBG_CALL(Dbg_unused_sec(lml, 557cce0e03bSab196087 isp)); 558cce0e03bSab196087 } 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * If this section provides no data, and isn't 5637c478bd9Sstevel@tonic-gate * referenced, then it can be discarded as well. 5647c478bd9Sstevel@tonic-gate * Note, if this is the first input section 5657c478bd9Sstevel@tonic-gate * associated to an output section, let it 5667c478bd9Sstevel@tonic-gate * through, there may be a legitimate reason why 5677c478bd9Sstevel@tonic-gate * the user wants a null section. Discarding 5687c478bd9Sstevel@tonic-gate * additional sections is intended to remove the 5697c478bd9Sstevel@tonic-gate * empty clutter the compilers have a habit of 5707c478bd9Sstevel@tonic-gate * creating. Don't provide an unused diagnostic 5717c478bd9Sstevel@tonic-gate * as these sections aren't typically the users 5727c478bd9Sstevel@tonic-gate * creation. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate if (ifl && dataidx && 5757c478bd9Sstevel@tonic-gate ((isp->is_flags & FLG_IS_SECTREF) == 0) && 5767c478bd9Sstevel@tonic-gate (isp->is_shdr->sh_size == 0)) { 5777c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_DISCARD; 5787c478bd9Sstevel@tonic-gate continue; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 58212b8e62eSrie * The first input section triggers the creation 58312b8e62eSrie * of the associated output section. 58412b8e62eSrie */ 58512b8e62eSrie if (osp->os_scn == NULL) { 58612b8e62eSrie shidx++; 58712b8e62eSrie 58812b8e62eSrie if (create_outsec(ofl, sgp, osp, ptype, 58912b8e62eSrie shidx, fixalign) == S_ERROR) 59012b8e62eSrie return (S_ERROR); 59112b8e62eSrie } 59212b8e62eSrie 59312b8e62eSrie dataidx++; 59412b8e62eSrie 59512b8e62eSrie /* 59612b8e62eSrie * Create a new output data buffer for each 59712b8e62eSrie * input data buffer, thus linking the new 5987c478bd9Sstevel@tonic-gate * buffers to the new elf output structures. 5997c478bd9Sstevel@tonic-gate * Simply make the new data buffers point to 6007c478bd9Sstevel@tonic-gate * the old data. 6017c478bd9Sstevel@tonic-gate */ 60212b8e62eSrie if ((data = elf_newdata(osp->os_scn)) == NULL) { 6031007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 6047c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ELF_NEWDATA), 6057c478bd9Sstevel@tonic-gate ofl->ofl_name); 6067c478bd9Sstevel@tonic-gate return (S_ERROR); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate *data = *(isp->is_indata); 60912b8e62eSrie isp->is_indata = data; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if ((fixalign == TRUE) && (ptype == PT_LOAD) && 61212b8e62eSrie (shidx == 1) && (dataidx == 1)) 61369112eddSAli Bahrami data->d_align = sgp->sg_align; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 616dd94ecefSrie * Save the first TLS data buffer, as this is 617dd94ecefSrie * the start of the TLS segment. Realign this 618dd94ecefSrie * buffer based on the alignment requirements 619dd94ecefSrie * of all the TLS input sections. 6207c478bd9Sstevel@tonic-gate */ 6211d9df23bSab196087 if ((flags & FLG_OF_TLSPHDR) && 6227c478bd9Sstevel@tonic-gate (isp->is_shdr->sh_flags & SHF_TLS)) { 623dd94ecefSrie if (tlsdata == 0) 624dd94ecefSrie tlsdata = data; 6255aefb655Srie tlsdata->d_align = 6265aefb655Srie ld_lcm(tlsdata->d_align, 6277c478bd9Sstevel@tonic-gate isp->is_shdr->sh_addralign); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate #if defined(_ELF64) && defined(_ILP32) 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * 4106312, the 32-bit ELF64 version of ld 6337c478bd9Sstevel@tonic-gate * needs to be able to create large .bss 6347c478bd9Sstevel@tonic-gate * sections. The d_size member of Elf_Data 6357c478bd9Sstevel@tonic-gate * only allows 32-bits in _ILP32, so we build 6367c478bd9Sstevel@tonic-gate * multiple data-items that each fit into 32- 6377c478bd9Sstevel@tonic-gate * bits. libelf (4106398) can summ these up 6387c478bd9Sstevel@tonic-gate * into a 64-bit quantity. This only works 6397c478bd9Sstevel@tonic-gate * for NOBITS sections which don't have any 6407c478bd9Sstevel@tonic-gate * real data to maintain and don't require 6417c478bd9Sstevel@tonic-gate * large file support. 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate if (isp->is_shdr->sh_type == SHT_NOBITS) { 6447c478bd9Sstevel@tonic-gate Xword sz = isp->is_shdr->sh_size; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate while (sz >> 32) { 6477c478bd9Sstevel@tonic-gate data->d_size = SIZE_MAX; 6487c478bd9Sstevel@tonic-gate sz -= (Xword)SIZE_MAX; 64912b8e62eSrie 65012b8e62eSrie data = elf_newdata(osp->os_scn); 65112b8e62eSrie if (data == NULL) 6527c478bd9Sstevel@tonic-gate return (S_ERROR); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate data->d_size = (size_t)sz; 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate #endif 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* 6597c478bd9Sstevel@tonic-gate * If this segment requires rounding realign the 6607c478bd9Sstevel@tonic-gate * first data buffer associated with the first 6617c478bd9Sstevel@tonic-gate * section. 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate if ((frst++ == 0) && 6647c478bd9Sstevel@tonic-gate (sgp->sg_flags & FLG_SG_ROUND)) { 6657c478bd9Sstevel@tonic-gate Xword align; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (data->d_align) 6687c478bd9Sstevel@tonic-gate align = (Xword) 6697c478bd9Sstevel@tonic-gate S_ROUND(data->d_align, 6707c478bd9Sstevel@tonic-gate sgp->sg_round); 6717c478bd9Sstevel@tonic-gate else 6727c478bd9Sstevel@tonic-gate align = sgp->sg_round; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate data->d_align = (size_t)align; 6757c478bd9Sstevel@tonic-gate } 676c8937b0dSRichard Lowe 677c8937b0dSRichard Lowe if ((data->d_size != 0) && (nonempty == NULL)) { 678c8937b0dSRichard Lowe nonempty = osp; 679c8937b0dSRichard Lowe } 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * Clear the szoutrels counter so that it can be used 6847c478bd9Sstevel@tonic-gate * again in the building of relocs. See machrel.c. 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate osp->os_szoutrels = 0; 6877c478bd9Sstevel@tonic-gate } 688c8937b0dSRichard Lowe 689c8937b0dSRichard Lowe /* 690c8937b0dSRichard Lowe * We need to raise the alignment of any empty sections at the 691c8937b0dSRichard Lowe * start of a segment to be at least as aligned as the first 692c8937b0dSRichard Lowe * non-empty section, such that the empty and first non-empty 693c8937b0dSRichard Lowe * sections are placed at the same offset. 694c8937b0dSRichard Lowe */ 695c8937b0dSRichard Lowe if (nonempty != NULL) { 696c8937b0dSRichard Lowe Elf_Data *ne = NULL; 697c8937b0dSRichard Lowe Xword pad_align = 1; 698c8937b0dSRichard Lowe 699c8937b0dSRichard Lowe ne = elf_getdata(nonempty->os_scn, NULL); 700c8937b0dSRichard Lowe assert(ne != NULL); 701c8937b0dSRichard Lowe 702c8937b0dSRichard Lowe do { 703c8937b0dSRichard Lowe pad_align = ld_lcm(pad_align, ne->d_align); 704c8937b0dSRichard Lowe ne = elf_getdata(nonempty->os_scn, ne); 705c8937b0dSRichard Lowe } while (ne != NULL); 706c8937b0dSRichard Lowe 707c8937b0dSRichard Lowe for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 708c8937b0dSRichard Lowe Elf_Data *d = NULL; 709c8937b0dSRichard Lowe 710c8937b0dSRichard Lowe /* Stop at the first non-empty section */ 711c8937b0dSRichard Lowe if (osp == nonempty) 712c8937b0dSRichard Lowe break; 713c8937b0dSRichard Lowe 714c8937b0dSRichard Lowe d = elf_getdata(osp->os_scn, NULL); 715c8937b0dSRichard Lowe 716*6b817808SRichard Lowe if (d != NULL) 717c8937b0dSRichard Lowe d->d_align = pad_align; 718c8937b0dSRichard Lowe } 719c8937b0dSRichard Lowe } 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7234f680cc6SAli Bahrami * Did we use ELF features from the osabi range? If so, 7244f680cc6SAli Bahrami * update the ELF header osabi fields. If this doesn't happen, 7254f680cc6SAli Bahrami * those fields remain 0, reflecting a generic System V ELF ABI. 7264f680cc6SAli Bahrami */ 7274f680cc6SAli Bahrami if (ofl->ofl_flags & FLG_OF_OSABI) { 7284f680cc6SAli Bahrami ofl->ofl_nehdr->e_ident[EI_OSABI] = ELFOSABI_SOLARIS; 7294f680cc6SAli Bahrami ofl->ofl_nehdr->e_ident[EI_ABIVERSION] = EAV_SUNW_CURRENT; 7304f680cc6SAli Bahrami } 7314f680cc6SAli Bahrami 7324f680cc6SAli Bahrami /* 7337c478bd9Sstevel@tonic-gate * Build an empty PHDR. 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate if (nseg) { 7367c478bd9Sstevel@tonic-gate if ((ofl->ofl_phdr = elf_newphdr(ofl->ofl_welf, 7377c478bd9Sstevel@tonic-gate nseg)) == NULL) { 7381007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_NEWPHDR), 7391007fd6fSAli Bahrami ofl->ofl_name); 7407c478bd9Sstevel@tonic-gate return (S_ERROR); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* 7457c478bd9Sstevel@tonic-gate * If we need to generate a memory model, pad the image. 7467c478bd9Sstevel@tonic-gate */ 7479039eeafSab196087 if (flags1 & FLG_OF1_MEMORY) { 7487c478bd9Sstevel@tonic-gate if (pad_outfile(ofl) == S_ERROR) 7497c478bd9Sstevel@tonic-gate return (S_ERROR); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * After all the basic input file processing, all data pointers are 7547c478bd9Sstevel@tonic-gate * referencing two types of memory: 7557c478bd9Sstevel@tonic-gate * 756635216b6SRod Evans * - allocated memory, ie. elf structures, internal link editor 757635216b6SRod Evans * structures, and any new sections that have been created. 7587c478bd9Sstevel@tonic-gate * 759635216b6SRod Evans * - original input file mmap'ed memory, ie. the actual data 7607c478bd9Sstevel@tonic-gate * sections of the input file images. 7617c478bd9Sstevel@tonic-gate * 7627c478bd9Sstevel@tonic-gate * Up until now, the only memory modifications have been carried out on 7637c478bd9Sstevel@tonic-gate * the allocated memory. Before carrying out any relocations, write the 7647c478bd9Sstevel@tonic-gate * new output file image and reassign any necessary data pointers to the 7657c478bd9Sstevel@tonic-gate * output files memory image. This insures that any relocation 7667c478bd9Sstevel@tonic-gate * modifications are made to the output file image and not to the input 7677c478bd9Sstevel@tonic-gate * file image, thus preventing the creation of dirty pages and reducing 7687c478bd9Sstevel@tonic-gate * the overall swap space requirement. 7697c478bd9Sstevel@tonic-gate * 7707c478bd9Sstevel@tonic-gate * Write out the elf structure so as to create the new file image. 7717c478bd9Sstevel@tonic-gate */ 7727c478bd9Sstevel@tonic-gate if ((ofl->ofl_size = (size_t)elf_update(ofl->ofl_welf, 7737c478bd9Sstevel@tonic-gate ELF_C_WRIMAGE)) == (size_t)-1) { 7741007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_UPDATE), 7755aefb655Srie ofl->ofl_name); 7767c478bd9Sstevel@tonic-gate return (S_ERROR); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * Initialize the true `ofl' information with the memory images address 7817c478bd9Sstevel@tonic-gate * and size. This will be used to write() out the image once any 7827c478bd9Sstevel@tonic-gate * relocation processing has been completed. We also use this image 7837c478bd9Sstevel@tonic-gate * information to setup a new Elf descriptor, which is used to obtain 7847c478bd9Sstevel@tonic-gate * all the necessary elf pointers within the new output image. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate if ((ofl->ofl_elf = elf_begin(0, ELF_C_IMAGE, 7877c478bd9Sstevel@tonic-gate ofl->ofl_welf)) == NULL) { 7881007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_BEGIN), 7895aefb655Srie ofl->ofl_name); 7907c478bd9Sstevel@tonic-gate return (S_ERROR); 7917c478bd9Sstevel@tonic-gate } 7925aefb655Srie if ((ofl->ofl_nehdr = elf_getehdr(ofl->ofl_elf)) == NULL) { 7931007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETEHDR), 7945aefb655Srie ofl->ofl_name); 7957c478bd9Sstevel@tonic-gate return (S_ERROR); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) 7987c478bd9Sstevel@tonic-gate if ((ofl->ofl_phdr = elf_getphdr(ofl->ofl_elf)) == NULL) { 7991007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETPHDR), 8001007fd6fSAli Bahrami ofl->ofl_name); 8017c478bd9Sstevel@tonic-gate return (S_ERROR); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * Reinitialize the section descriptors, section headers and obtain new 8067c478bd9Sstevel@tonic-gate * output data buffer pointers (these will be used to perform any 8077c478bd9Sstevel@tonic-gate * relocations). 8087c478bd9Sstevel@tonic-gate */ 80957ef7aa9SRod Evans ndx = 0; 81057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 8117c478bd9Sstevel@tonic-gate Phdr *_phdr = &(sgp->sg_phdr); 812cce0e03bSab196087 Os_desc *osp; 81357ef7aa9SRod Evans Aliste idx2; 8147c478bd9Sstevel@tonic-gate Boolean recorded = FALSE; 8157c478bd9Sstevel@tonic-gate 81657ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 81712b8e62eSrie /* 81812b8e62eSrie * Make sure that an output section was originally 81912b8e62eSrie * created. Input sections that had been marked as 82012b8e62eSrie * discarded may have made an output section 821492e5a89Srie * unnecessary. Remove this alist entry so that 822492e5a89Srie * future output section descriptor processing doesn't 823492e5a89Srie * have to compensate for this empty section. 82412b8e62eSrie */ 825492e5a89Srie if (osp->os_scn == NULL) { 82657ef7aa9SRod Evans aplist_delete(sgp->sg_osdescs, &idx2); 82712b8e62eSrie continue; 828492e5a89Srie } 82957ef7aa9SRod Evans if ((osp->os_scn = 83057ef7aa9SRod Evans elf_getscn(ofl->ofl_elf, ++ndx)) == NULL) { 8311007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 8325aefb655Srie MSG_INTL(MSG_ELF_GETSCN), ofl->ofl_name, 8335aefb655Srie ndx); 8347c478bd9Sstevel@tonic-gate return (S_ERROR); 8357c478bd9Sstevel@tonic-gate } 83657ef7aa9SRod Evans if ((osp->os_shdr = 83757ef7aa9SRod Evans elf_getshdr(osp->os_scn)) == NULL) { 8381007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 8395aefb655Srie MSG_INTL(MSG_ELF_GETSHDR), ofl->ofl_name); 8407c478bd9Sstevel@tonic-gate return (S_ERROR); 8417c478bd9Sstevel@tonic-gate } 84257ef7aa9SRod Evans if ((fixalign == TRUE) && sgp->sg_fscn && 8437c478bd9Sstevel@tonic-gate (recorded == FALSE)) { 84457ef7aa9SRod Evans size_t fndx; 8457c478bd9Sstevel@tonic-gate Elf_Scn *scn; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate scn = sgp->sg_fscn; 8487c478bd9Sstevel@tonic-gate if ((fndx = elf_ndxscn(scn)) == SHN_UNDEF) { 8491007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 8507c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ELF_NDXSCN), 8517c478bd9Sstevel@tonic-gate ofl->ofl_name); 8527c478bd9Sstevel@tonic-gate return (S_ERROR); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate if (ndx == fndx) { 8557c478bd9Sstevel@tonic-gate sgp->sg_fscn = osp->os_scn; 8567c478bd9Sstevel@tonic-gate recorded = TRUE; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate if ((osp->os_outdata = 8617c478bd9Sstevel@tonic-gate elf_getdata(osp->os_scn, NULL)) == NULL) { 8621007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 8635aefb655Srie MSG_INTL(MSG_ELF_GETDATA), ofl->ofl_name); 8647c478bd9Sstevel@tonic-gate return (S_ERROR); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * If this section is part of a loadable segment insure 8697c478bd9Sstevel@tonic-gate * that the segments alignment is appropriate. 8707c478bd9Sstevel@tonic-gate */ 8717c478bd9Sstevel@tonic-gate if (_phdr->p_type == PT_LOAD) { 8725aefb655Srie _phdr->p_align = ld_lcm(_phdr->p_align, 8737c478bd9Sstevel@tonic-gate osp->os_shdr->sh_addralign); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate return (1); 8787c478bd9Sstevel@tonic-gate } 879