sections.c revision bf994817a71d4ac680198e25fe79d13c247306e0
/*
* 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
*
*/
/*
* Module sections. Initialize special sections
*/
#define ELF_TARGET_AMD64
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <link.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
inline static void
{
/* LINTED - only used for assert() */
int err;
ofl->ofl_locscnt--;
ofl->ofl_dynlocscnt--;
/* Remove from sort section? */
}
}
}
inline static void
{
/* LINTED - only used for assert() */
int err;
ofl->ofl_scopecnt--;
ofl->ofl_elimcnt++;
ofl->ofl_dynscopecnt--;
/* Remove from sort section? */
}
}
inline static void
{
/*
* Skip section symbols, these were never collected in the
* first place.
*/
if (type == STT_SECTION)
return;
/*
* Determine if the whole file is being removed. Remove any
* file symbol, and any symbol that is not associated with a
* section, provided the symbol has not been identified as
* (update) required.
*/
return;
}
} else {
/*
* Global symbols can only be eliminated when the interfaces of
* an object have been defined via versioning/scoping.
*/
if (!SYM_IS_HIDDEN(sdp))
return;
/*
* Remove any unreferenced symbols that are not associated with
* a section.
*/
return;
}
}
/*
* Do not discard any symbols that are associated with non-allocable
* segments.
*/
else
}
}
}
/*
* There are situations where we may count output sections (ofl_shdrcnt)
* that are subsequently eliminated from the output object. Whether or
* not this happens cannot be known until all input has been seen and
* section elimination code has run. However, the situations where this
* outcome is possible are known, and are flagged by setting FLG_OF_ADJOSCNT.
*
* If FLG_OF_ADJOSCNT is set, this routine makes a pass over the output
* sections. If an unused output section is encountered, we decrement
* ofl->ofl_shdrcnt and remove the section name from the .shstrtab string
* table (ofl->ofl_shdrsttab).
*
* This code must be kept in sync with the similar code
* found in outfile.c:ld_create_outfile().
*/
static void
{
return;
/*
* For each output section, look at the input sections to find at least
* one input section that has not been eliminated. If none are found,
* the -z ignore processing above has eliminated that output section.
*/
int keep = 0, os_isdescs_idx;
/* Input section is tagged for discard? */
continue;
/*
* If the file is discarded, it will take
* the section with it.
*/
if (ifl &&
continue;
/*
* We have found a kept input section,
* so the output section will be created.
*/
keep = 1;
break;
}
/*
* If no section of this name was kept, decrement
* the count and remove the name from .shstrtab.
*/
if (keep == 0) {
/* LINTED - only used for assert() */
int err;
ofl->ofl_shdrcnt--;
}
}
}
}
/*
* If -zignore has been in effect, scan all input files to determine if the
* file, or sections from the file, have been referenced. If not, the file or
* some of the files sections can be discarded. If sections are to be
* discarded, rescan the output relocations and the symbol table and remove
* the relocations and symbol entries that are no longer required.
*
* Note: It's possible that a section which is being discarded has contributed
* to the GOT table or the PLT table. However, we can't at this point
* eliminate the corresponding entries. This is because there could well
* be other sections referencing those same entries, but we don't have
* the infrastructure to determine this. So, keep the PLT and GOT
* entries in the table in case someone wants them.
* Note: The section to be affected needs to be allocatable.
* So even if -zignore is in effect, if the section is not allocatable,
* we do not eliminate it.
*/
static uintptr_t
{
/*
* Diagnose (-D unused) a completely unreferenced file.
*/
continue;
/*
* Before scanning the whole symbol table to determine if
* symbols should be discard - quickly (relatively) scan the
* sections to determine if any are to be discarded.
*/
discard = 0;
discard++;
break;
}
}
}
/*
* No sections are to be 'ignored'
*/
continue;
/*
* We know that we have discarded sections. Scan the symbol
* table for this file to determine if symbols need to be
* discarded that are associated with the 'ignored' sections.
*/
/*
* If the symbol definition has been resolved to another
* file, or the symbol has already been discarded or
* eliminated, skip it.
*/
continue;
/*
* Complete the investigation of the symbol.
*/
}
}
/*
* If we were only here to solicit debugging diagnostics, we're done.
*/
return (1);
/*
* Scan all output relocations searching for those against discarded or
* ignored sections. If one is found, decrement the total outrel count.
*/
continue;
continue;
else
if (!(flags & FLG_REL_PLT))
ofl->ofl_reloccntsub++;
ofl->ofl_relocrelcnt--;
}
/*
* As a result of our work here, the number of output sections may
* have decreased. Trigger a call to adjust_os_count().
*/
return (1);
}
/*
* Allocate Elf_Data, Shdr, and Is_desc structures for a new
* section.
*
* entry:
* ofl - Output file descriptor
* shtype - SHT_ type code for section.
* shname - String giving the name for the new section.
* entcnt - # of items contained in the data part of the new section.
* This value is multiplied against the known element size
* for the section type to determine the size of the data
* area for the section. It is only meaningful in cases where
* the section type has a non-zero element size. In other cases,
* the caller must set the size fields in the *ret_data and
* *ret_shdr structs manually.
* ret_isec, ret_shdr, ret_data - Address of pointers to
* receive address of newly allocated structs.
*
* exit:
* On error, returns S_ERROR. On success, returns (1), and the
* ret_ pointers have been updated to point at the new structures,
* which have been filled in. To finish the task, the caller must
* update any fields within the supplied descriptors that differ
* from its needs, and then call ld_place_section().
*/
static uintptr_t
{
typedef struct sec_info {
} SEC_INFO_T;
const SEC_INFO_T *sec_info;
/*
* For each type of section, we have a distinct set of
* SEC_INFO_T values. This macro defines a static structure
* containing those values and generates code to set the sec_info
* pointer to refer to it. The pointer in sec_info remains valid
* outside of the declaration scope because the info_s struct is static.
*
* We can't determine the value of M_WORD_ALIGN at compile time, so
* a different variant is used for those cases.
*/
{ \
sh_entsize}; \
}
{ \
sh_entsize}; \
}
switch (shtype) {
case SHT_PROGBITS:
/*
* SHT_PROGBITS sections contain are used for many
* different sections. Alignments and flags differ.
* Some have a standard entsize, and others don't.
* We set some defaults here, but there is no expectation
* that they are correct or complete for any specific
* purpose. The caller must provide the correct values.
*/
break;
case SHT_SYMTAB:
break;
case SHT_DYNSYM:
break;
case SHT_SUNW_LDYNSYM:
break;
case SHT_STRTAB:
/*
* A string table may or may not be allocable, depending
* on context, so we leave that flag unset and leave it to
* the caller to add it if necessary.
*
* String tables do not have a standard entsize, so
* we set it to 0.
*/
break;
case SHT_RELA:
/*
* Relocations with an addend (Everything except 32-bit X86).
* The caller is expected to set all section header flags.
*/
break;
case SHT_REL:
/*
* Relocations without an addend (32-bit X86 only).
* The caller is expected to set all section header flags.
*/
break;
case SHT_HASH:
break;
case SHT_SUNW_symsort:
case SHT_SUNW_tlssort:
break;
case SHT_DYNAMIC:
/*
* A dynamic section may or may not be allocable, depending
* on context, so we leave that flag unset and leave it to
* the caller to add it if necessary.
*/
break;
case SHT_NOBITS:
/*
* SHT_NOBITS is used for BSS-type sections. The size and
* alignment depend on the specific use and must be adjusted
* by the caller.
*/
break;
case SHT_INIT_ARRAY:
case SHT_FINI_ARRAY:
case SHT_PREINIT_ARRAY:
sizeof (Addr))
break;
case SHT_SYMTAB_SHNDX:
/*
* Note that these sections are created to be associated
* with both symtab and dynsym symbol tables. However, they
* are non-allocable in all cases, because the runtime
* linker has no need for this information. It is purely
* informational, used by elfdump(1), debuggers, etc.
*/
break;
case SHT_SUNW_cap:
break;
case SHT_SUNW_capchain:
sizeof (Capchain));
break;
case SHT_SUNW_capinfo:
#if _ELF64
sizeof (Capinfo));
#else
sizeof (Capinfo));
#endif
break;
case SHT_SUNW_move:
break;
case SHT_SUNW_syminfo:
/*
* The sh_info field of the SHT_*_syminfo section points
* to the header index of the associated .dynamic section,
* so we also set SHF_INFO_LINK.
*/
break;
case SHT_SUNW_verneed:
case SHT_SUNW_verdef:
/*
* The info for verneed and versym happen to be the same.
* The entries in these sections are not of uniform size,
* so we set the entsize to 0.
*/
break;
case SHT_SUNW_versym:
sizeof (Versym));
break;
default:
/* Should not happen: fcn called with unknown section type */
assert(0);
return (S_ERROR);
}
/*
* Allocate and initialize the Elf_Data structure.
*/
return (S_ERROR);
/*
* Allocate and initialize the Shdr structure.
*/
return (S_ERROR);
/*
* Allocate and initialize the Is_desc structure.
*/
return (S_ERROR);
return (1);
}
/*
* Use an existing input section as a template to create a new
* input section with the same values as the original, other than
* the size of the data area which is supplied by the caller.
*
* entry:
* ofl - Output file descriptor
* ifl - Input file section to use as a template
* size - Size of data area for new section
* ret_isec, ret_shdr, ret_data - Address of pointers to
* receive address of newly allocated structs.
*
* exit:
* On error, returns S_ERROR. On success, returns (1), and the
* ret_ pointers have been updated to point at the new structures,
* which have been filled in. To finish the task, the caller must
* update any fields within the supplied descriptors that differ
* from its needs, and then call ld_place_section().
*/
static uintptr_t
{
/*
* Allocate and initialize the Elf_Data structure.
*/
return (S_ERROR);
/*
* Allocate and initialize the Shdr structure.
*/
return (S_ERROR);
/*
* Allocate and initialize the Is_desc structure.
*/
return (S_ERROR);
return (1);
}
/*
* Build a .bss section for allocation of tentative definitions. Any `static'
* .bss definitions would have been associated to their own .bss sections and
* thus collected from the input files. `global' .bss definitions are tagged
* as COMMON and do not cause any associated .bss section elements to be
* generated. Here we add up all these COMMON symbols and generate the .bss
* section required to represent them.
*/
{
/*
* Allocate header structs. We will set the name ourselves below,
* and there is no entcnt for a BSS. So, the shname and entcnt
* arguments are 0.
*/
return (S_ERROR);
#if defined(_ELF64)
#endif
}
/*
* Retain this .*bss input section as this will be where global symbol
* references are added.
*/
return (S_ERROR);
/*
* If relocations exist against a .*bss section, a section symbol must
* be created for the section in the .dynsym symbol table.
*/
else
ofl->ofl_dynshdrcnt++;
}
}
return (1);
}
/*
* Build a SHT_{INIT|FINI|PREINIT}ARRAY section (specified via
* ld -z *array=name).
*/
static uintptr_t
{
return (1);
entcount = 0;
entcount++;
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
/*
* Create relocations against this section to initialize it to the
* function addresses.
*/
/*
* Fabricate the relocation information (as if a relocation record had
* been input - see init_rel()).
*/
reld.rel_roffset = 0;
reld.rel_raddend = 0;
/*
* Create a minimal relocation record to satisfy process_sym_reloc()
* debugging requirements.
*/
continue;
}
}
return (ret);
}
/*
* Build a comment section (-Qy option).
*/
static uintptr_t
{
return (S_ERROR);
}
/*
* Make the dynamic section. Calculate the size of any strings referenced
* within this structure, they will be added to the global string table
* (.dynstr). This routine should be called before make_dynstr().
*
* This routine must be maintained in parallel with update_odynamic()
* in update.c
*/
static uintptr_t
{
int unused = 0;
/*
* Select the required string table.
*/
if (OFL_IS_STATIC_OBJ(ofl))
else
/*
* Only a limited subset of DT_ entries apply to relocatable
* objects. See the comment at the head of update_odynamic() in
* update.c for details.
*/
return (S_ERROR);
/* new_section() does not set SHF_ALLOC. Add it if needed */
if (not_relobj)
/*
* Reserve entries for any needed dependencies.
*/
continue;
/*
* If this dependency didn't satisfy any symbol references,
* generate a debugging diagnostic (ld(1) -Dunused can be used
* to display these). If this is a standard needed dependency,
* and -z ignore is in effect, drop the dependency. Explicitly
* defined dependencies (i.e., -N dep) don't get dropped, and
* are flagged as being required to simplify update_odynamic()
* processing.
*/
if (unused++ == 0)
continue;
}
/*
* If this object is a lazyload reserve a DT_POSFLAG_1 entry.
*/
cnt++;
return (S_ERROR);
cnt++;
/*
* If the needed entry contains the $ORIGIN token make sure
* the associated DT_1_FLAGS entry is created.
*/
}
}
if (unused)
if (not_relobj) {
/*
*/
/*
* Reserve entries for _init() and _fini() section addresses.
*/
cnt++;
}
cnt++;
}
/*
* Reserve entries for any soname, filter name (shared libs
* only), run-path pointers, cache names and audit requirements.
*/
if (ofl->ofl_soname) {
cnt++;
return (S_ERROR);
}
if (ofl->ofl_filtees) {
cnt++;
return (S_ERROR);
/*
* If the filtees entry contains the $ORIGIN token
* make sure the associated DT_1_FLAGS entry is created.
*/
MSG_ORIG(MSG_STR_ORIGIN))) {
}
}
}
return (S_ERROR);
/*
* If the rpath entry contains the $ORIGIN token make sure
* the associated DT_1_FLAGS entry is created.
*/
}
}
if (not_relobj) {
if (ofl->ofl_config) {
cnt++;
return (S_ERROR);
/*
* If the config entry contains the $ORIGIN token
* make sure the associated DT_1_FLAGS entry is created.
*/
}
}
if (ofl->ofl_depaudit) {
cnt++;
return (S_ERROR);
}
cnt++;
return (S_ERROR);
}
/*
* Reserve entries for the HASH, STRTAB, STRSZ, SYMTAB, SYMENT,
* and CHECKSUM.
*/
cnt += 6;
/*
* If we are including local functions at the head of
* the dynsym, then also reserve entries for DT_SUNW_SYMTAB
* and DT_SUNW_SYMSZ.
*/
if (OFL_ALLOW_LDYNSYM(ofl))
cnt += 2;
if ((ofl->ofl_dynsymsortcnt > 0) ||
(ofl->ofl_dyntlssortcnt > 0))
cnt++; /* DT_SUNW_SORTENT */
if (ofl->ofl_dynsymsortcnt > 0)
if (ofl->ofl_dyntlssortcnt > 0)
cnt++; /* RELACOUNT */
cnt++;
cnt += 2;
cnt += 2;
/*
* If we have plt's reserve a PLT, PLTSZ, PLTREL and JMPREL.
*/
if (ofl->ofl_pltcnt)
cnt += 3;
/*
* If pltpadding is needed (Sparcv9)
*/
if (ofl->ofl_pltpad)
/*
* If we have any relocations reserve a REL, RELSZ and
* RELENT entry.
*/
if (ofl->ofl_relocsz)
cnt += 3;
/*
* If a syminfo section is required create SYMINFO, SYMINSZ,
* and SYMINENT entries.
*/
if (flags & FLG_OF_SYMINFO)
cnt += 3;
/*
* If there are any partially initialized sections allocate
* MOVEENT, MOVESZ and MOVETAB.
*/
if (ofl->ofl_osmove)
cnt += 3;
/*
* Allocate one DT_REGISTER entry for every register symbol.
*/
/*
* Reserve a entry for each '-zrtldinfo=...' specified
* on the command line.
*/
cnt++;
/*
* These two entries should only be placed in a segment
* which is writable. If it's a read-only segment
* (due to mapfile magic, e.g. libdl.so.1) then don't allocate
* these entries.
*/
cnt++; /* FEATURE_1 */
if (ofl->ofl_osinterp)
cnt++; /* DEBUG */
}
/*
* Capabilities require a .dynamic entry for the .SUNW_cap
* section.
*/
cnt++; /* SUNW_CAP */
/*
* Symbol capabilities require a .dynamic entry for the
* .SUNW_capinfo section.
*/
if (ofl->ofl_oscapinfo)
cnt++; /* SUNW_CAPINFO */
/*
* Capabilities chain information requires a .SUNW_capchain
* entry, an entry size, and total size.
*/
if (ofl->ofl_oscapchain)
if (flags & FLG_OF_SYMBOLIC)
cnt++; /* SYMBOLIC */
}
/*
* Account for Architecture dependent .dynamic entries, and defaults.
*/
/*
* DT_FLAGS, DT_FLAGS_1, DT_SUNW_STRPAD, and DT_NULL. Also,
* allow room for the unused extra DT_NULLs. These are included
* to allow an ELF editor room to add items later.
*/
/*
* DT_SUNW_LDMACH. Used to hold the ELF machine code of the
* linker that produced the output object. This information
* allows us to determine whether a given object was linked
* natively, or by a linker running on a different type of
* system. This information can be valuable if one suspects
* that a problem might be due to alignment or byte order issues.
*/
cnt++;
/*
* Determine the size of the section from the number of entries.
*/
/*
* There are several tags that are specific to the Solaris osabi
* range which we unconditionally put into any dynamic section
* we create (e.g. DT_SUNW_STRPAD or DT_SUNW_LDMACH). As such,
* any Solaris object with a dynamic section should be tagged as
* ELFOSABI_SOLARIS.
*/
}
/*
* Build the GOT section and its associated relocation entries.
*/
{
return (S_ERROR);
return (S_ERROR);
return (1);
}
/*
* Build an interpreter section.
*/
static uintptr_t
{
/*
* If -z nointerp is in effect, don't create an interpreter section.
*/
return (1);
/*
* We always build an .interp section for dynamic executables. However
* if the user has specifically specified an interpreter we'll build
* this section for any output (presumably the user knows what they are
* doing. refer ABI section 5-4, and ld.1 man page use of -I).
*/
return (1);
/*
* In the case of a dynamic executable supply a default interpreter
* if a specific interpreter has not been specified.
*/
return (S_ERROR);
ofl->ofl_osinterp =
}
/*
* Common function used to build the SHT_SUNW_versym section, SHT_SUNW_syminfo
* section, and SHT_SUNW_capinfo section. Each of these sections provide
* additional symbol information, and their size parallels the associated
* symbol table.
*/
static Os_desc *
{
/*
* We don't know the size of this section yet, so set it to 0. The
* size gets filled in after the associated symbol table is sized.
*/
}
/*
* Determine whether a symbol capability is redundant because the object
* capabilities are more restrictive.
*/
inline static int
{
/*
* Inspect any platform capabilities. If the object defines platform
* capabilities, then the object will only be loaded for those
* platforms. A symbol capability set that doesn't define the same
* platforms is redundant, and a symbol capability that does not provide
* at least one platform name that matches a platform name in the object
* capabilities will never execute (as the object wouldn't have been
* loaded).
*/
return (1);
/*
* If the symbol capability set defines platforms, and the object
* doesn't, then the symbol set is more restrictive.
*/
return (0);
/*
* Next, inspect any machine name capabilities. If the object defines
* machine name capabilities, then the object will only be loaded for
* those machines. A symbol capability set that doesn't define the same
* machine names is redundant, and a symbol capability that does not
* provide at least one machine name that matches a machine name in the
* object capabilities will never execute (as the object wouldn't have
* been loaded).
*/
return (1);
/*
* If the symbol capability set defines machine names, and the object
* doesn't, then the symbol set is more restrictive.
*/
return (0);
/*
* Next, inspect any hardware capabilities. If the objects hardware
* capabilities are greater than or equal to that of the symbols
* capabilities, then the symbol capability set is redundant. If the
* symbols hardware capabilities are greater that the objects, then the
* symbol set is more restrictive.
*
* Note that this is a somewhat arbitrary definition, as each capability
* bit is independent of the others, and some of the higher order bits
* could be considered to be less important than lower ones. However,
* this is the only reasonable non-subjective definition.
*/
return (1);
return (0);
/*
* Finally, inspect the remaining hardware capabilities.
*/
return (1);
return (0);
}
/*
* Capabilities values might have been assigned excluded values. These
* excluded values should be removed before calculating any capabilities
* sections size.
*/
static void
{
/*
* First determine whether any bits should be excluded.
*/
return;
}
static void
{
char *estr;
/*
* First determine whether any strings should be excluded.
*/
break;
}
}
}
return;
/*
* Traverse the current strings, then delete the excluded strings,
* and finally display the resolved strings.
*/
if (DBG_ENABLED) {
}
}
break;
}
}
}
if (DBG_ENABLED) {
}
}
}
/*
* Build a capabilities section.
*/
static uintptr_t
{
int title = 0;
/*
* Determine which string table to use for any CA_SUNW_MACH,
* CA_SUNW_PLAT, or CA_SUNW_ID strings.
*/
if (OFL_IS_STATIC_OBJ(ofl))
else
/*
* If symbol capabilities have been collected, but no symbols are left
* referencing these capabilities, promote the capability groups back
* to an object capability definition.
*/
ofl->ofl_capsymcnt = 0;
}
/*
* Remove any excluded capabilities.
*/
/*
* Determine how many entries are required for any object capabilities.
*/
size++;
size++;
size++;
/*
* Only identify a capabilities group if the group has content. If a
* capabilities identifier exists, and no other capabilities have been
* supplied, remove the identifier. This scenario could exist if a
* user mistakenly defined a lone identifier, or if an identified group
* was overridden so as to clear the existing capabilities and the
* identifier was not also cleared.
*/
if (size)
size++;
else
}
if (size)
size++; /* Add CA_SUNW_NULL */
/*
* Determine how many entries are required for any symbol capabilities.
*/
if (ofl->ofl_capsymcnt) {
/*
* If there are no object capabilities, a CA_SUNW_NULL entry
* is required before any symbol capabilities.
*/
if (size == 0)
size++;
}
if (size == 0)
return (NULL);
return (S_ERROR);
return (S_ERROR);
/*
* Fill in any object capabilities. If there is an identifier, then the
* identifier comes first. The remaining items follow in precedence
* order, although the order isn't important for runtime verification.
*/
return (S_ERROR);
}
/*
* Insert any platform name strings in the appropriate string
* table. The capability value can't be filled in yet, as the
* final offset of the strings isn't known until later.
*/
return (S_ERROR);
}
}
/*
* Insert the machine name strings in the appropriate string
* table. The capability value can't be filled in yet, as the
* final offset of the strings isn't known until later.
*/
return (S_ERROR);
}
}
}
}
}
/*
* Fill in any symbol capabilities.
*/
if (ofl->ofl_capgroups) {
/*
* Insert the identifier string in the
* appropriate string table. The capability
* value can't be filled in yet, as the final
* offset of the string isn't known until later.
*/
return (S_ERROR);
}
/*
* Insert the platform name string in the
* appropriate string table. The capability
* value can't be filled in yet, as the final
* offset of the string isn't known until later.
*/
return (S_ERROR);
CA_SUNW_PLAT, 0);
}
}
/*
* Insert the machine name string in the
* appropriate string table. The capability
* value can't be filled in yet, as the final
* offset of the string isn't known until later.
*/
return (S_ERROR);
CA_SUNW_MACH, 0);
}
}
}
}
}
/*
* If any object capabilities are available, determine
* whether these symbol capabilities are less
* restrictive, and hence redundant.
*/
continue;
/*
* Indicate any files that provide redundant symbol
* capabilities.
*/
}
}
}
/*
* If capabilities strings are required, the sh_info field of the
* section header will be set to the associated string table.
*/
/*
* Place these capabilities in the output file.
*/
return (S_ERROR);
/*
* If symbol capabilities are required, then a .SUNW_capinfo section is
* also created. This table will eventually be sized to match the
* associated symbol table.
*/
if (ofl->ofl_capfamilies) {
return (S_ERROR);
/*
* If we're generating a dynamic object, capabilities family
* members are maintained in a .SUNW_capchain section.
*/
if (ofl->ofl_capchaincnt &&
return (S_ERROR);
return (S_ERROR);
}
}
return (1);
}
/*
* Build the PLT section and its associated relocation entries.
*/
static uintptr_t
{
/*
* On sparc, account for the NOP at the end of the plt.
*/
return (S_ERROR);
return (S_ERROR);
return (1);
}
/*
* Make the hash table. Only built for dynamic executables and shared
* libraries, and provides hashed lookup into the global symbol table
* (.dynsym) for the run-time linker to resolve symbol lookups.
*/
static uintptr_t
{
/*
* Allocate section header structures. We set entcnt to 0
* because it's going to change after we place this section.
*/
return (S_ERROR);
/*
* Place the section first since it will affect the local symbol
* count.
*/
ofl->ofl_oshash =
return (S_ERROR);
/*
* Calculate the number of output hash buckets.
*/
/*
* The size of the hash table is determined by
*
* i. the initial nbucket and nchain entries (2)
* ii. the number of buckets (calculated above)
* iii. the number of chains (this is based on the number of
* symbols in the .dynsym array).
*/
/*
* Finalize the section header and data buffer initialization.
*/
return (S_ERROR);
return (1);
}
/*
* Generate the standard symbol table. Contains all locals and globals,
* and resides in a non-allocatable section (ie. it can be stripped).
*/
static uintptr_t
{
/*
* Create the section headers. Note that we supply an ent_cnt
* of 0. We won't know the count until the section has been placed.
*/
return (S_ERROR);
/*
* Place the section first since it will affect the local symbol
* count.
*/
return (S_ERROR);
/*
* At this point we've created all but the 'shstrtab' section.
* Determine if we have to use 'Extended Sections'. If so - then
* also create a SHT_SYMTAB_SHNDX section.
*/
return (S_ERROR);
return (S_ERROR);
}
/*
* Calculated number of symbols, which need to be augmented by
* the (yet to be created) .shstrtab entry.
*/
/*
* Finalize the section header and data buffer initialization.
*/
/*
* If we created a SHT_SYMTAB_SHNDX - then set it's sizes too.
*/
if (xisec) {
}
return (1);
}
/*
* Build a dynamic symbol table. These tables reside in the text
* segment of a dynamic executable or shared library.
*
* .SUNW_ldynsym contains local function symbols
* .dynsym contains only globals symbols
*
* The two tables are created adjacent to each other, with .SUNW_ldynsym
* coming first.
*/
static uintptr_t
{
int allow_ldynsym;
/*
* Unless explicitly disabled, always produce a .SUNW_ldynsym section
* when it is allowed by the file type, even if the resulting
* table only ends up with a single STT_FILE in it. There are
* two reasons: (1) It causes the generation of the DT_SUNW_SYMTAB
* entry in the .dynamic section, which is something we would
* like to encourage, and (2) Without it, we cannot generate
* the associated .SUNW_dyn[sym|tls]sort sections, which are of
* value to DTrace.
*
* In practice, it is extremely rare for an object not to have
* local symbols for .SUNW_ldynsym, so 99% of the time, we'd be
* doing it anyway.
*/
/*
* Create the section headers. Note that we supply an ent_cnt
* of 0. We won't know the count until the section has been placed.
*/
return (S_ERROR);
return (S_ERROR);
/*
* Place the section(s) first since it will affect the local symbol
* count.
*/
if (allow_ldynsym &&
return (S_ERROR);
ofl->ofl_osdynsym =
return (S_ERROR);
/*
* Finalize the section header and data buffer initialization.
*/
/*
* An ldynsym contains local function symbols. It is not
* used for linking, but if present, serves to allow better
* stack traces to be generated in contexts where the symtab
* is not available. (dladdr(), or stripped executable/library files).
*/
if (allow_ldynsym) {
}
return (1);
}
/*
* index sections for the .SUNW_ldynsym/.dynsym pair that present data
* and function symbols sorted by address.
*/
static uintptr_t
{
/* Only do it if the .SUNW_ldynsym section is present */
if (!OFL_ALLOW_LDYNSYM(ofl))
return (1);
/* .SUNW_dynsymsort */
if (ofl->ofl_dynsymsortcnt > 0) {
return (S_ERROR);
return (S_ERROR);
}
/* .SUNW_dyntlssort */
if (ofl->ofl_dyntlssortcnt > 0) {
return (S_ERROR);
return (S_ERROR);
}
return (1);
}
/*
* Helper routine for make_dynsym_shndx. Builds a
* a SHT_SYMTAB_SHNDX for .dynsym or .SUNW_ldynsym, without knowing
* which one it is.
*/
static uintptr_t
{
return (S_ERROR);
return (S_ERROR);
return (1);
}
/*
* Build a SHT_SYMTAB_SHNDX for the .dynsym, and .SUNW_ldynsym
*/
static uintptr_t
{
/*
* If there is a .SUNW_ldynsym, generate a section for its extended
* index section as well.
*/
if (OFL_ALLOW_LDYNSYM(ofl)) {
return (S_ERROR);
}
/* The Generate a section for the dynsym */
return (S_ERROR);
return (1);
}
/*
* Build a string table for the section headers.
*/
static uintptr_t
{
return (S_ERROR);
/*
* Place the section first, as it may effect the number of section
* headers to account for.
*/
return (S_ERROR);
return (1);
}
/*
* Build a string section for the standard symbol table.
*/
static uintptr_t
{
/*
* This string table consists of all the global and local symbols.
* Account for null bytes at end of the file name and the beginning
* of section.
*/
return (S_ERROR);
return (S_ERROR);
/* Set the size of the data area */
ofl->ofl_osstrtab =
}
/*
* Build a string table for the dynamic symbol table.
*/
static uintptr_t
{
/*
* If producing a .SUNW_ldynsym, account for the initial STT_FILE
* symbol that precedes the scope reduced global symbols.
*/
if (OFL_ALLOW_LDYNSYM(ofl)) {
return (S_ERROR);
ofl->ofl_dynscopecnt++;
}
/*
* Account for any local, named register symbols. These locals are
* required for reference from DT_REGISTER .dynamic entries.
*/
if (ofl->ofl_regsyms) {
int ndx;
continue;
if (!SYM_IS_HIDDEN(sdp) &&
continue;
continue;
return (S_ERROR);
}
}
/*
*/
return (S_ERROR);
}
return (S_ERROR);
/* Make it allocable if necessary */
/* Set the size of the data area */
ofl->ofl_osdynstr =
}
/*
* Generate an output relocation section which will contain the relocation
* information to be applied to the `osp' section.
*
* If (osp == NULL) then we are creating the coalesced relocation section
*/
static uintptr_t
{
char *sectname;
const char *rel_prefix;
/* LINTED */
/* REL */
} else {
/* RELA */
}
if (osp) {
return (S_ERROR);
} else {
sectname = (char *)rel_prefix;
}
/*
* Keep track of total size of 'output relocations' (to be stored
* in .dynamic)
*/
/* LINTED */
return (S_ERROR);
if (osp) {
/*
* The sh_info field of the SHT_REL* sections points to the
* section the relocations are to be applied to.
*/
}
return (S_ERROR);
/*
* Associate this relocation section to the section its going to
* relocate.
*/
if (osp) {
/*
* This is used primarily so that we can update
* SHT_GROUP[sect_no] entries to point to the
* created output relocation sections.
*/
/*
* If the input relocation section had the SHF_GROUP
* flag set - propagate it to the output relocation
* section.
*/
break;
}
}
} else
/*
* If this is the first relocation section we've encountered save it
* so that the .dynamic entry can be initialized accordingly.
*/
return (1);
}
/*
* Generate version needed section.
*/
static uintptr_t
{
/*
* verneed sections do not have a constant element size, so the
* value of ent_cnt specified here (0) is meaningless.
*/
return (S_ERROR);
/* During version processing we calculated the total size. */
ofl->ofl_osverneed =
}
/*
* Generate a version definition section.
*
* o the SHT_SUNW_verdef section defines the versions that exist within this
* image.
*/
static uintptr_t
{
/*
* Reserve a string table entry for the base version dependency (other
* dependencies have symbol representations, which will already be
* accounted for during symbol processing).
*/
if (OFL_IS_STATIC_OBJ(ofl))
else
return (S_ERROR);
/*
* verdef sections do not have a constant element size, so the
* value of ent_cnt specified here (0) is meaningless.
*/
return (S_ERROR);
/* During version processing we calculated the total size. */
ofl->ofl_osverdef =
}
/*
* This routine is called when -z nopartial is in effect.
*/
{
return (S_ERROR);
if (align != 0) {
}
return (S_ERROR);
/*
* Retain handle to this .data input section. Variables using move
* sections (partial initialization) will be redirected here when
* such global references are added and '-z nopartial' is in effect.
*/
return (S_ERROR);
ofl->ofl_dynshdrcnt++;
}
return (1);
}
/*
* Make .sunwmove section
*/
{
int cnt = 1;
return (S_ERROR);
return (S_ERROR);
/*
* Copy move entries
*/
continue;
}
return (S_ERROR);
return (1);
}
/*
* Given a relocation descriptor that references a string table
* input section, locate the string referenced and return a pointer
* to it.
*/
static const char *
{
/*
* In the case of an STT_SECTION symbol, the addend of the
* relocation gives the offset into the string section. For
* other symbol types, the symbol value is the offset.
*/
/*
* For SHT_RELA, the addend value is found in the
* rel_raddend field of the relocation.
*/
} else { /* REL and STT_SECTION */
/*
* For SHT_REL, the "addend" is not part of the relocation
* record. Instead, it is found at the relocation target
* address.
*/
return (0);
}
}
/*
* First pass over the relocation records for string table merging.
* Build lists of relocations and symbols that will need modification,
* and insert the strings they reference into the mstrtab string table.
*
* entry:
* ofl, osp - As passed to ld_make_strmerge().
* mstrtab - String table to receive input strings. This table
* must be in its first (initialization) pass and not
* yet cooked (st_getstrtab_sz() not yet called).
* rel_alpp - APlist to receive pointer to any relocation
* descriptors with STT_SECTION symbols that reference
* one of the input sections being merged.
* sym_alpp - APlist to receive pointer to any symbols that reference
* one of the input sections being merged.
* rcp - Pointer to cache of relocation descriptors to examine.
* Either &ofl->ofl_actrels (active relocations)
* or &ofl->ofl_outrels (output relocations).
*
* exit:
* On success, rel_alpp and sym_alpp are updated, and
* any strings in the mergeable input sections referenced by
* a relocation has been entered into mstrtab. True (1) is returned.
*
* On failure, False (0) is returned.
*/
static int
{
const char *name;
continue;
/*
* Remember symbol for use in the third pass. There is no
* reason to save a given symbol more than once, so we take
* advantage of the fact that relocations to a given symbol
* tend to cluster in the list. If this is the same symbol
* we saved last time, don't bother.
*/
NULL)
return (0);
}
/* Enter the string into our new string table */
return (0);
/*
* If this is an STT_SECTION symbol, then the second pass
* will need to modify this relocation, so hang on to it.
*/
return (0);
}
return (1);
}
/*
* If the output section has any SHF_MERGE|SHF_STRINGS input sections,
* replace them with a single merged/compressed input section.
*
* entry:
* ofl - Output file descriptor
* osp - Output section descriptor
* rel_alpp, sym_alpp, - Address of 2 APlists, to be used
* for internal processing. On the initial call to
* ld_make_strmerge, these list pointers must be NULL.
* The caller is encouraged to pass the same lists back for
* successive calls to this function without freeing
* them in between calls. This causes a single pair of
* memory allocations to be reused multiple times.
*
* exit:
* If section merging is possible, it is done. If no errors are
* encountered, True (1) is returned. On error, S_ERROR.
*
* The contents of rel_alpp and sym_alpp on exit are
* undefined. The caller can free them, or pass them back to a subsequent
* call to this routine, but should not examine their contents.
*/
static uintptr_t
{
int st_setstring_status;
/* If string table compression is disabled, there's nothing to do */
return (1);
/*
* Pass over the mergeable input sections, and if they haven't
* all been discarded, create a string table.
*/
continue;
/*
* We have at least one non-discarded section.
* Create a string table descriptor.
*/
return (S_ERROR);
break;
}
/* If no string table was created, we have no mergeable sections */
return (1);
/*
* This routine has to make 3 passes:
*
* 1) Examine all relocations, insert strings from relocations
* to the mergeable input sections into the string table.
* 2) Modify the relocation values to be correct for the
* new merged section.
* 3) Modify the symbols used by the relocations to reference
* the new section.
*
* These passes cannot be combined:
* - The string table code works in two passes, and all
* strings have to be loaded in pass one before the
* offset of any strings can be determined.
* - Multiple relocations reference a single symbol, so the
* symbol cannot be modified until all relocations are
* fixed.
*
* The number of relocations related to section merging is usually
* a mere fraction of the overall active and output relocation lists,
* and the number of symbols is usually a fraction of the number
* of related relocations. We therefore build APlists for the
* relocations and symbols in the first pass, and then use those
* lists to accelerate the operation of pass 2 and 3.
*
* Reinitialize the lists to a completely empty state.
*/
/*
* Pass 1:
*
* Every relocation related to this output section (and the input
* sections that make it up) is found in either the active, or the
* output relocation list, depending on whether the relocation is to
* be processed by this invocation of the linker, or inserted into the
* output object.
*
* Build lists of relocations and symbols that will need modification,
* and insert the strings they reference into the mstrtab string table.
*/
&ofl->ofl_actrels) == 0)
goto return_s_error;
&ofl->ofl_outrels) == 0)
goto return_s_error;
/*
* Get the size of the new input section. Requesting the
* string table size "cooks" the table, and finalizes its contents.
*/
/* Create a new input section to hold the merged strings */
goto return_s_error;
/*
* Allocate a data buffer for the new input section.
* Then, associate the buffer with the string table descriptor.
*/
goto return_s_error;
goto return_s_error;
/* Add the new section to the output image */
goto return_s_error;
/*
* Pass 2:
*
* Revisit the relocation descriptors with STT_SECTION symbols
* that were saved by the first pass. Update each relocation
* record so that the offset it contains is for the new section
* instead of the original.
*/
const char *name;
/* Put the string into the merged string table */
if (st_setstring_status == -1) {
/*
* A failure to insert at this point means that
* something is corrupt. This isn't a resource issue.
*/
goto return_s_error;
}
/*
* Alter the relocation to access the string at the
* new offset in our new string table.
*
* For SHT_RELA platforms, it suffices to simply
* update the rel_raddend field of the relocation.
*
* For SHT_REL platforms, the new "addend" value
* needs to be written at the address being relocated.
* However, we can't alter the input sections which
* are mapped readonly, and the output image has not
* been created yet. So, we defer this operation,
* using the rel_raddend field of the relocation
* which is normally 0 on a REL platform, to pass the
* new "addend" value to ld_perform_outreloc() or
* ld_do_activerelocs(). The FLG_REL_NADDEND flag
* tells them that this is the case.
*/
/*
* Generate a symbol name string for STT_SECTION symbols
* that might reference our merged section. This shows up
* in debug output and helps show how the relocation has
* changed from its original input section to our merged one.
*/
goto return_s_error;
}
/*
* Pass 3:
*
* Modify the symbols referenced by the relocation descriptors
* so that they reference the new input section containing the
* merged strings instead of the original input sections.
*/
/*
* If we've already processed this symbol, don't do it
* twice. strmerge_pass1() uses a heuristic (relocations to
* the same symbol clump together) to avoid inserting a
* given symbol more than once, but repeat symbols in
* the list can occur.
*/
continue;
/*
* This is not an STT_SECTION symbol, so its
* value is the offset of the string within the
* input section. Update the address to reflect
* the address in our new merged section.
*/
if (st_setstring_status == -1) {
/*
* A failure to insert at this point means
* something is corrupt. This isn't a
* resource issue.
*/
goto return_s_error;
}
goto return_s_error;
}
/* Redirect the symbol to our new merged section */
}
/*
* There are no references left to the original input string sections.
* Mark them as discarded so they don't go into the output image.
* At the same time, add up the sizes of the replaced sections.
*/
data_size = 0;
continue;
}
/* Report how much space we saved in the output section */
return (1);
return (S_ERROR);
}
/*
* Update a data buffers size. A number of sections have to be created, and
* the sections header contributes to the size of the eventual section. Thus,
* a section may be created, and once all associated sections have been created,
* we return to establish the required section size.
*/
inline static void
{
}
/*
* The following sections are built after all input file processing and symbol
* validation has been carried out. The order is important (because the
* addition of a section adds a new symbol there is a chicken and egg problem
* of maintaining the appropriate counts). By maintaining a known order the
* individual routines can compensate for later, known, additions.
*/
{
/*
* Generate any special sections.
*/
if (flags & FLG_OF_ADDVERS)
return (S_ERROR);
return (S_ERROR);
/*
* Create a capabilities section if required.
*/
return (S_ERROR);
/*
*/
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
/*
* Make the .plt section. This occurs after any other relocation
* sections are generated (see reloc_init()) to ensure that the
* associated relocation section is after all the other relocation
* sections.
*/
return (S_ERROR);
/*
* Determine whether any sections or files are not referenced. Under
* -Dunused a diagnostic for any unused components is generated, under
* -zignore the component is removed from the final output.
*/
return (S_ERROR);
}
/*
* If we have detected a situation in which previously placed
* output sections may have been discarded, perform the necessary
* readjustment.
*/
/*
* Do any of the output sections contain input sections that
* are candidates for string table merging? For each such case,
* we create a replacement section, insert it, and discard the
* originals.
*
* rel_alpp and sym_alpp are used by ld_make_strmerge()
* for its internal processing. We are responsible for the
* initialization and cleanup, and ld_make_strmerge() handles the rest.
* This allows us to reuse a single pair of memory buffers, allocated
* for this processing, for all the output sections.
*/
int error_seen = 0;
S_ERROR)) {
error_seen = 1;
break;
}
}
if (error_seen != 0)
return (S_ERROR);
}
/*
* Add any necessary versioning information.
*/
if (!(flags & FLG_OF_NOVERSEC)) {
if ((flags & FLG_OF_VERNEED) &&
return (S_ERROR);
if ((flags & FLG_OF_VERDEF) &&
return (S_ERROR);
return (S_ERROR);
}
/*
* Create a syminfo section if necessary.
*/
if (flags & FLG_OF_SYMINFO) {
return (S_ERROR);
}
if (flags & FLG_OF_COMREL) {
/*
* If -zcombreloc is enabled then all relocations (except for
* the PLT's) are coalesced into a single relocation section.
*/
if (ofl->ofl_reloccnt) {
return (S_ERROR);
}
} else {
/*
* Create the required output relocation sections. Note, new
* sections may be added to the section list that is being
* traversed. These insertions can move the elements of the
* Alist such that a section descriptor is re-read. Recursion
* is prevented by maintaining a previous section pointer and
* insuring that this pointer isn't re-examined.
*/
return (S_ERROR);
}
}
}
/*
* If we're not building a combined relocation section, then
* build a .rel[a] section as required.
*/
if (ofl->ofl_relocrelsz) {
return (S_ERROR);
}
}
/*
* The PLT relocations are always in their own section, and we try to
* keep them at the end of the PLT table. We do this to keep the hot
* "data" PLT's at the head of the table nearer the .dynsym & .hash.
*/
return (S_ERROR);
}
/*
* Finally build the symbol and section header sections.
*/
if (flags & FLG_OF_DYNAMIC) {
return (S_ERROR);
/*
* A number of sections aren't necessary within a relocatable
* object, even if -dy has been used.
*/
if (!(flags & FLG_OF_RELOBJ)) {
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
return (S_ERROR);
}
}
/*
* Do we need to make a SHT_SYMTAB_SHNDX section
* for the dynsym. If so - do it now.
*/
if (ofl->ofl_osdynsym &&
return (S_ERROR);
}
return (S_ERROR);
return (S_ERROR);
} else {
/*
* Do we need to make a SHT_SYMTAB_SHNDX section
* for the dynsym. If so - do it now.
*/
if (ofl->ofl_osdynsym &&
return (S_ERROR);
}
}
return (S_ERROR);
/*
* Now that we've created all output sections, adjust the size of the
* SHT_SUNW_versym and SHT_SUNW_syminfo section, which are dependent on
* the associated symbol table sizes.
*/
if (OFL_IS_STATIC_OBJ(ofl))
else
if (ofl->ofl_osversym)
if (ofl->ofl_ossyminfo)
}
/*
* Now that we've created all output sections, adjust the size of the
* SHT_SUNW_capinfo, which is dependent on the associated symbol table
* size.
*/
if (ofl->ofl_oscapinfo) {
/*
* Symbol capabilities symbols are placed directly after the
* STT_FILE symbol, section symbols, and any register symbols.
* Effectively these are the first of any series of demoted
* (scoped) symbols.
*/
if (OFL_IS_STATIC_OBJ(ofl))
else
}
return (1);
}
/*
* Build an additional data section - used to back OBJT symbol definitions
* added with a mapfile.
*/
Is_desc *
{
return (isec);
}
/*
* Build an additional text section - used to back FUNC symbol definitions
* added with a mapfile.
*/
Is_desc *
{
/*
* Insure the size is sufficient to contain the minimum return
* instruction.
*/
/*
* Fill the buffer with the appropriate return instruction.
* Note that there is no need to swap bytes on a non-native,
* link, as the data being copied is given in bytes.
*/
/*
* If size was larger than required, and the target supplies
* a fill function, use it to fill the balance. If there is no
* fill function, we accept the 0-fill supplied by libld_calloc().
*/
return (isec);
}