/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
*
* Copyright 2011, Richard Lowe.
*/
/*
* This file contains the functions responsible for opening the output file
* image, associating the appropriate input elf structures with the new image,
* and obtaining new elf structures to define the new image.
*/
#include <stdio.h>
#include <fcntl.h>
#include <link.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <debug.h>
#include <unistd.h>
#include "msg.h"
#include "_libld.h"
/*
* Determine a least common multiplier. Input sections contain an alignment
* requirement, which elf_update() uses to insure that the section is aligned
* correctly off of the base of the elf image. We must also insure that the
* sections mapping is congruent with this alignment requirement. For each
* input section associated with a loadable segment determine whether the
* segments alignment must be adjusted to compensate for a sections alignment
* requirements.
*/
{
if ((_a = a) == 0)
return (b);
if ((_b = b) == 0)
return (a);
return ((a / _a) * b);
}
/*
* Open the output file and insure the correct access modes.
*/
{
/*
* Determine the required file mode from the type of output file we
* are creating.
*/
? 0777 : 0666;
/* Determine if the output file already exists */
/*
* It is not a regular file, so don't delete it
* or allow it to be deleted. This allows root
* verification links.
*/
} else {
/*
* It's a regular file, so unlink it. In standard
* Unix fashion, the old file will continue to
* exist until its link count drops to 0 and no
* process has the file open. In the meantime, we
* create a new file (inode) under the same name,
* available for new use.
*
* The advantage of this policy is that creating
* a new executable or sharable library does not
* corrupt existing processes using the old file.
* A possible disadvantage is that if the existing
* file has a (link_count > 1), the other names will
* continue to reference the old inode, thus
* breaking the link.
*
* A subtlety here is that POSIX says we are not
* supposed to replace a non-writable file, which
* is something that unlink() is happy to do. The
* only 100% reliable test against this is to open
* the file for non-destructive write access. If the
* open succeeds, we are clear to unlink it, and if
* not, then the error generated is the error we
* need to report.
*/
mode)) < 0) {
return (S_ERROR);
}
} else {
}
return (S_ERROR);
}
}
}
/*
* Open (or create) the output file name (ofl_fd acts as a global
* flag to ldexit() signifying whether the output file should be
* removed or not on error).
*/
mode)) < 0) {
return (S_ERROR);
}
return (1);
}
/*
* If we are creating a memory model we need to update the present memory image.
* Use elf_update(ELF_C_NULL) to calculate the offset of each section and their
* associated data buffers. From this information determine what padding is
* required.
*
* Two actions are necessary to convert the present disc image into a memory
* image:
*
* - Loadable segments must be padded so that the next segment virtual
* address and file offset are the same.
*
* - NOBITS sections must be converted into allocated, null filled sections.
*/
static uintptr_t
{
/*
* Update all the elf structures. This will assign offsets to the
* section headers and data buffers as they relate to the new image.
*/
return (S_ERROR);
}
return (S_ERROR);
}
/*
* Initialize the offset by skipping the Elf header and program
* headers.
*/
/*
* Traverse the segment list looking for loadable segments.
*/
/*
* If we've already processed a loadable segment, the `scn'
* variable will be initialized to the last section that was
* part of that segment. Add sufficient padding to this section
* to cause the next segments virtual address and file offset to
* be the same.
*/
offset);
return (S_ERROR);
}
return (S_ERROR);
}
/*
* Traverse the output sections for this segment calculating the
* offset of each section. Retain the final section descriptor
* as this will be where any padding buffer will be added.
*/
/*
* If this is a NOBITS output section convert all of
* its associated input sections into real, null filled,
* data buffers, and change the section to PROGBITS.
*/
}
/*
* If this is a loadable segment retain the last output section
* descriptor. This acts both as a flag that a loadable
* segment has been seen, and as the segment to which a padding
* buffer will be added.
*/
}
return (1);
}
/*
* Create an output section. The first instance of an input section triggers
* the creation of a new output section.
*/
static uintptr_t
{
/*
* Get a section descriptor for the section.
*/
return (S_ERROR);
}
/*
* Get a new section header table entry and copy the pertinent
* information from the in-core descriptor.
*/
return (S_ERROR);
}
/*
* If this is the first section within a loadable segment, and the
* alignment needs to be updated, record this section.
*/
/*
* If not building a relocatable object, remove any of the
* following flags, as they have been acted upon and are not
* meaningful in the output:
* SHF_ORDERED, SHF_LINK_ORDER, SHF_GROUP
* For relocatable objects, we allow them to propagate to
* the output object to be handled by the next linker that
* sees them.
*/
/*
* If this is a TLS section, save it so that the PT_TLS program header
* information can be established after the output image has been
* initially created. At this point, all TLS input sections are ordered
* as they will appear in the output image.
*/
AL_CNT_OFL_OSTLSSEG) == NULL))
return (S_ERROR);
return (0);
}
/*
* Create the elf structures that allow the input data to be associated with the
* new image:
*
* - define the new elf image using elf_begin(),
*
* - obtain an elf header for the image,
*
* - traverse the input segments and create a program header array to define
* the required segments,
*
* - traverse the output sections for each segment assigning a new section
* descriptor and section header for each,
*
* - traverse the input sections associated with each output section and
* assign a new data descriptor to each (each output section becomes a
* linked list of input data buffers).
*/
{
/*
* If DF_1_NOHDR or FLG_OF1_VADDR were set,
* we need to do alignment adjustment.
*/
if ((flags1 & FLG_OF1_VADDR) ||
}
if (flags1 & FLG_OF1_MEMORY) {
cmd = ELF_C_IMAGE;
fd = 0;
} else {
cmd = ELF_C_WRITE;
}
/*
* If there are any ordered sections, handle them here.
*/
return (S_ERROR);
/*
* Tell the access library about our new temporary file.
*/
return (S_ERROR);
}
/*
* Obtain a new Elf header.
*/
return (S_ERROR);
}
int frst = 0;
/*
* Count the number of segments that will go in the program
* header table. If a segment is empty, ignore it.
*/
if (!(flags & FLG_OF_RELOBJ)) {
/*
* If the program header type belongs to the os range,
* the resulting object is ELFOSABI_SOLARIS.
*/
/*
* If we are generating an interp section (and
* thus an associated PT_INTERP program header
* entry) also generate a PT_PHDR program header
* entry. This allows the kernel to generate
* the appropriate aux vector entries to pass to
* Note that if an image was generated with an
* interp section, but no associated PT_PHDR
* program header entry, the kernel will simply
* pass the interpreter an open file descriptor
* when the image is executed).
*/
if (ofl->ofl_osinterp)
nseg++;
if (ofl->ofl_osinterp)
nseg++;
} else if (ptype == PT_DYNAMIC) {
if (flags & FLG_OF_DYNAMIC)
nseg++;
if (flags & FLG_OF_TLSPHDR)
nseg++;
} else if (ptype == PT_SUNW_UNWIND) {
if (ofl->ofl_unwindhdr)
nseg++;
} else if (ptype == PT_SUNWDTRACE) {
if (ofl->ofl_dtracesym)
nseg++;
} else if (ptype == PT_SUNWCAP) {
nseg++;
} else if (ptype == PT_SUNWSTACK) {
nseg++;
nseg++;
/*
* If this is a segment for which
* we are not making a program header,
* don't increment nseg
*/
nseg++;
}
}
/*
* Establish any processing unique to the first loadable
* segment.
*/
ptloadidx++;
/*
* If the first loadable segment is not supposed to
* include the ELF or program headers, alignments
* of the following segments need to be fixed,
* plus a .dynamic FLAGS1 setting is required.
*/
}
shidx = 0;
int os_isdescs_idx;
dataidx = 0;
/*
* An input section in the list that has
* been previously marked to be discarded
* should be completely ignored.
*/
continue;
/*
* At this point we know whether a section has
* been referenced. If it hasn't, and the whole
* file hasn't been referenced (which would have
* been caught in ignore_section_processing()),
* give a diagnostic (-D unused,detail) or
* discard the section if -zignore is in effect.
*/
if (ifl &&
isp));
continue;
} else {
isp));
}
}
/*
* If this section provides no data, and isn't
* referenced, then it can be discarded as well.
* Note, if this is the first input section
* associated to an output section, let it
* through, there may be a legitimate reason why
* the user wants a null section. Discarding
* additional sections is intended to remove the
* empty clutter the compilers have a habit of
* creating. Don't provide an unused diagnostic
* as these sections aren't typically the users
* creation.
*/
continue;
}
/*
* The first input section triggers the creation
* of the associated output section.
*/
shidx++;
return (S_ERROR);
}
dataidx++;
/*
* Create a new output data buffer for each
* input data buffer, thus linking the new
* buffers to the new elf output structures.
* Simply make the new data buffers point to
* the old data.
*/
return (S_ERROR);
}
/*
* Save the first TLS data buffer, as this is
* the start of the TLS segment. Realign this
* buffer based on the alignment requirements
* of all the TLS input sections.
*/
if ((flags & FLG_OF_TLSPHDR) &&
if (tlsdata == 0)
}
/*
* 4106312, the 32-bit ELF64 version of ld
* needs to be able to create large .bss
* sections. The d_size member of Elf_Data
* only allows 32-bits in _ILP32, so we build
* multiple data-items that each fit into 32-
* bits. libelf (4106398) can summ these up
* into a 64-bit quantity. This only works
* for NOBITS sections which don't have any
* real data to maintain and don't require
* large file support.
*/
while (sz >> 32) {
return (S_ERROR);
}
}
#endif
/*
* If this segment requires rounding realign the
* first data buffer associated with the first
* section.
*/
if ((frst++ == 0) &&
else
}
}
}
/*
* Clear the szoutrels counter so that it can be used
* again in the building of relocs. See machrel.c.
*/
osp->os_szoutrels = 0;
}
/*
* We need to raise the alignment of any empty sections at the
* start of a segment to be at least as aligned as the first
* non-empty section, such that the empty and first non-empty
* sections are placed at the same offset.
*/
do {
/* Stop at the first non-empty section */
break;
if (d != NULL)
}
}
}
/*
* Did we use ELF features from the osabi range? If so,
* update the ELF header osabi fields. If this doesn't happen,
* those fields remain 0, reflecting a generic System V ELF ABI.
*/
}
/*
* Build an empty PHDR.
*/
if (nseg) {
return (S_ERROR);
}
}
/*
* If we need to generate a memory model, pad the image.
*/
if (flags1 & FLG_OF1_MEMORY) {
return (S_ERROR);
}
/*
* After all the basic input file processing, all data pointers are
* referencing two types of memory:
*
* - allocated memory, ie. elf structures, internal link editor
* structures, and any new sections that have been created.
*
* - original input file mmap'ed memory, ie. the actual data
* sections of the input file images.
*
* Up until now, the only memory modifications have been carried out on
* the allocated memory. Before carrying out any relocations, write the
* new output file image and reassign any necessary data pointers to the
* output files memory image. This insures that any relocation
* modifications are made to the output file image and not to the input
* file image, thus preventing the creation of dirty pages and reducing
* the overall swap space requirement.
*
* Write out the elf structure so as to create the new file image.
*/
return (S_ERROR);
}
/*
* Initialize the true `ofl' information with the memory images address
* and size. This will be used to write() out the image once any
* relocation processing has been completed. We also use this image
* information to setup a new Elf descriptor, which is used to obtain
* all the necessary elf pointers within the new output image.
*/
return (S_ERROR);
}
return (S_ERROR);
}
if (!(flags & FLG_OF_RELOBJ))
return (S_ERROR);
}
/*
* Reinitialize the section descriptors, section headers and obtain new
* output data buffer pointers (these will be used to perform any
* relocations).
*/
ndx = 0;
/*
* Make sure that an output section was originally
* created. Input sections that had been marked as
* discarded may have made an output section
* unnecessary. Remove this alist entry so that
* future output section descriptor processing doesn't
* have to compensate for this empty section.
*/
continue;
}
ndx);
return (S_ERROR);
}
return (S_ERROR);
}
return (S_ERROR);
}
}
}
if ((osp->os_outdata =
return (S_ERROR);
}
/*
* If this section is part of a loadable segment insure
* that the segments alignment is appropriate.
*/
}
}
}
return (1);
}