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
ld_lcm(Xword a,Xword b)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
ld_open_outfile(Ofl_desc * ofl)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
pad_outfile(Ofl_desc * ofl)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
create_outsec(Ofl_desc * ofl,Sg_desc * sgp,Os_desc * osp,Word ptype,int shidx,Boolean fixalign)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
ld_create_outfile(Ofl_desc * ofl)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