xref: /illumos-gate/usr/src/cmd/sgs/libld/common/outfile.c (revision fb12490a)
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>
4413246550Sab #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 {
8013246550Sab 	mode_t		mode;
817c478bd9Sstevel@tonic-gate 	struct stat	status;
8213246550Sab 
830f5dca20Sab 	/*
840f5dca20Sab 	 * Determine the required file mode from the type of output file we
850f5dca20Sab 	 * are creating.
860f5dca20Sab 	 */
870f5dca20Sab 	mode = (ofl->ofl_flags & (FLG_OF_EXEC | FLG_OF_SHAROBJ))
88cce0e03bSab 	    ? 0777 : 0666;
890f5dca20Sab 
9013246550Sab 	/* Determine if the output file already exists */
9113246550Sab 	if (stat(ofl->ofl_name, &status) == 0) {
9213246550Sab 		if ((status.st_mode & S_IFMT) != S_IFREG) {
9313246550Sab 			/*
9413246550Sab 			 * It is not a regular file, so don't delete it
9513246550Sab 			 * or allow it to be deleted.  This allows root
9613246550Sab 			 * users to specify /dev/null output file for
9713246550Sab 			 * verification links.
9813246550Sab 			 */
9913246550Sab 			ofl->ofl_flags1 |= FLG_OF1_NONREG;
10013246550Sab 		} else {
10113246550Sab 			/*
10213246550Sab 			 * It's a regular file, so unlink it. In standard
10313246550Sab 			 * Unix fashion, the old file will continue to
10413246550Sab 			 * exist until its link count drops to 0 and no
10513246550Sab 			 * process has the file open. In the meantime, we
10613246550Sab 			 * create a new file (inode) under the same name,
10713246550Sab 			 * available for new use.
10813246550Sab 			 *
10913246550Sab 			 * The advantage of this policy is that creating
11013246550Sab 			 * a new executable or sharable library does not
11113246550Sab 			 * corrupt existing processes using the old file.
11213246550Sab 			 * A possible disadvantage is that if the existing
11313246550Sab 			 * file has a (link_count > 1), the other names will
11413246550Sab 			 * continue to reference the old inode, thus
11513246550Sab 			 * breaking the link.
1160f5dca20Sab 			 *
1170f5dca20Sab 			 * A subtlety here is that POSIX says we are not
1180f5dca20Sab 			 * supposed to replace a non-writable file, which
1190f5dca20Sab 			 * is something that unlink() is happy to do. The
1200f5dca20Sab 			 * only 100% reliable test against this is to open
1210f5dca20Sab 			 * the file for non-destructive write access. If the
1220f5dca20Sab 			 * open succeeds, we are clear to unlink it, and if
1230f5dca20Sab 			 * not, then the error generated is the error we
1240f5dca20Sab 			 * need to report.
12513246550Sab 			 */
1260f5dca20Sab 			if ((ofl->ofl_fd = open(ofl->ofl_name, O_RDWR,
1270f5dca20Sab 			    mode)) < 0) {
1280f5dca20Sab 				int	err = errno;
1290f5dca20Sab 
1300f5dca20Sab 				if (err != ENOENT) {
1311007fd6fSAli Bahrami 					ld_eprintf(ofl, ERR_FATAL,
1320f5dca20Sab 					    MSG_INTL(MSG_SYS_OPEN),
1330f5dca20Sab 					    ofl->ofl_name, strerror(err));
1340f5dca20Sab 					return (S_ERROR);
1350f5dca20Sab 				}
1360f5dca20Sab 			} else {
1370f5dca20Sab 				(void) close(ofl->ofl_fd);
1380f5dca20Sab 			}
1390f5dca20Sab 
14013246550Sab 			if ((unlink(ofl->ofl_name) == -1) &&
14113246550Sab 			    (errno != ENOENT)) {
14213246550Sab 				int err = errno;
14313246550Sab 
1441007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_FATAL,
145cce0e03bSab 				    MSG_INTL(MSG_SYS_UNLINK),
146cce0e03bSab 				    ofl->ofl_name, strerror(err));
14713246550Sab 				return (S_ERROR);
14813246550Sab 			}
14913246550Sab 		}
15013246550Sab 	}
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)1850bc07c75Srie pad_outfile(Ofl_desc *ofl)
1867c478bd9Sstevel@tonic-gate {
18757ef7aa9SRod Evans 	Aliste		idx1;
1887c478bd9Sstevel@tonic-gate 	off_t		offset;
1890bc07c75Srie 	Elf_Scn		*oscn = 0;
1900bc07c75Srie 	Sg_desc		*sgp;
1910bc07c75Srie 	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)) {
2180bc07c75Srie 		Phdr	*phdr = &(sgp->sg_phdr);
219cce0e03bSab 		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;
2318b891ae8SRichard Lowe 			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 			}
241*fb12490aSRichard Lowe 			if ((data->d_buf = libld_calloc(1, size)) == NULL)
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)) {
256cce0e03bSab 			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)
277492e5a89Srie 			oscn = osp->os_scn;
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 	return (1);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
28212b8e62eSrie /*
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 
3497c478bd9Sstevel@tonic-gate /*
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)3680bc07c75Srie ld_create_outfile(Ofl_desc *ofl)
3697c478bd9Sstevel@tonic-gate {
3700bc07c75Srie 	Sg_desc		*sgp;
371cce0e03bSab 	Os_desc		*osp;
3720bc07c75Srie 	Is_desc		*isp;
3730bc07c75Srie 	Elf_Data	*tlsdata = 0;
37457ef7aa9SRod Evans 	Aliste		idx1;
3751d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
3761d9df23bSab 	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 	 */
3889039eeafSab 	if ((flags1 & FLG_OF1_VADDR) ||
3894899432aSab 	    (ofl->ofl_dtflags_1 & DF_1_NOHDR)) {
3907c478bd9Sstevel@tonic-gate 		fixalign = TRUE;
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
3939039eeafSab 	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++;
4868b891ae8SRichard Lowe 			} else if (aplist_nitems(sgp->sg_osdescs) != 0) {
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) {
52457ef7aa9SRod Evans 				Elf_Data	*data;
52557ef7aa9SRod Evans 				Ifl_desc	*ifl = isp->is_file;
5267c478bd9Sstevel@tonic-gate 
527d2ef9fe9Sab 				/*
528d2ef9fe9Sab 				 * An input section in the list that has
529d2ef9fe9Sab 				 * been previously marked to be discarded
530d2ef9fe9Sab 				 * should be completely ignored.
531d2ef9fe9Sab 				 */
532d2ef9fe9Sab 				if (isp->is_flags & FLG_IS_DISCARD)
533d2ef9fe9Sab 					continue;
534d2ef9fe9Sab 
5357c478bd9Sstevel@tonic-gate 				/*
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) {
551cce0e03bSab 						isp->is_flags |= FLG_IS_DISCARD;
552cce0e03bSab 						DBG_CALL(Dbg_unused_sec(lml,
553cce0e03bSab 						    isp));
554cce0e03bSab 						continue;
555cce0e03bSab 					} else {
556cce0e03bSab 						DBG_CALL(Dbg_unused_sec(lml,
557cce0e03bSab 						    isp));
558cce0e03bSab 					}
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 				 */
6211d9df23bSab 				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,
627dd94ecefSrie 					    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 
7166b817808SRichard Lowe 				if (d != NULL)
7176b817808SRichard Lowe 					d->d_align = pad_align;
718c8937b0dSRichard Lowe 			}
719c8937b0dSRichard Lowe 		}
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate 
7224f680cc6SAli Bahrami 	/*
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 
7327c478bd9Sstevel@tonic-gate 	/*
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 	 */
7479039eeafSab 	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
760635216b6SRod Evans 	 *	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)) {
8110bc07c75Srie 		Phdr	*_phdr = &(sgp->sg_phdr);
812cce0e03bSab 		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