sections.c revision ca4eed8b351c42874d1c1d9360d832914a0ffd1b
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* 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.
*/
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
}
}
}
/*
* 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.
*
* which haven't been referenced (and hence 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.
*/
/* LINTED */
if ((isc == 0) ||
continue;
continue;
else
if (!(flags & FLG_REL_PLT))
ofl->ofl_reloccntsub++;
ofl->ofl_relocrelcnt--;
}
}
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:
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:
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_move:
/*
* 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_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.
*/
{
uint_t ident;
/*
* 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 .*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;
reld.rel_typedata = 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;
/*
* 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 has an accompanying shared object definition
* determine if an alternative shared object name has been
* specified.
*/
/*
* 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++;
-1)
return (S_ERROR);
}
if (ofl->ofl_filtees) {
cnt++;
-1)
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++;
-1)
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++;
-1)
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 */
}
/*
*/
cnt++; /* SUNW_CAP */
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.
*/
}
/*
* 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 =
}
/*
*/
static uintptr_t
{
/*
* Determine how many entries are required.
*/
if (ofl->ofl_hwcap_1)
size++;
if (ofl->ofl_sfcap_1)
size++;
if (size == 0)
return (1);
size++; /* Add CA_SUNW_NULL */
return (S_ERROR);
return (S_ERROR);
if (ofl->ofl_hwcap_1) {
cap++;
}
if (ofl->ofl_sfcap_1) {
cap++;
}
/*
* If we're not creating a relocatable object, save the output section
* to trigger the creation of an associated program header.
*/
}
/*
* 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.
*/
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 + NULL symbol).
*/
/*
* 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
{
/*
* We increment the number of sections in the output object
* (ofl->ofl_shdrcnt) as we add them. However, if -z ignore
* processing is in effect, the number of sections later removed
* is not reflected in that count. Updating the count as we
* remove these sections is a relatively expensive operation.
* Hence, if -z ignore is in use, we recompute the number of
* sections in a single final pass.
*/
/*
* 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.
*/
ofl->ofl_ossymtab =
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 null first entry, the FILE symbol, and the .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);
/*
* One extra section header entry for the 'null' entry.
*/
/*
* 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;
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.
*/
}
/*
* Associate this relocation section to the section its going to
* relocate.
*/
return (S_ERROR);
if (osp) {
/*
* We associate the input relocation sections - with
* the newly created output relocation section.
*
* 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).
*/
return (S_ERROR);
} 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 =
}
/*
* Common function used to build both the SHT_SUNW_versym
* section and the SHT_SUNW_syminfo section. Each of these sections
* provides additional symbol information.
*/
static Os_desc *
{
/*
* We don't know the size of this section yet, so set it to 0.
* It gets filled in after the dynsym is sized.
*/
}
/*
* Build a .sunwbss section for allocation of tentative definitions.
*/
{
/*
* 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);
/*
* Retain this .sunwbss input section as this will be where global
* symbol references are added.
*/
return (S_ERROR);
return (1);
}
/*
* This routine is called when -z nopartial is in effect.
*/
{
return (S_ERROR);
if (align != 0) {
}
return (S_ERROR);
/*
* Retain this .sunwdata1 input section as this will
* be where global
* symbol references are added.
*/
return (S_ERROR);
ofl->ofl_dynshdrcnt++;
}
return (1);
}
/*
* Make .sunwmove section
*/
{
int cnt = 1;
return (S_ERROR);
return (S_ERROR);
/*
* Copy move entries
*/
continue;
continue;
cnt++;
}
}
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_aplist - APlist to receive pointer to any relocation
* descriptors with STT_SECTION symbols that reference
* one of the input sections being merged.
* sym_aplist - APlist to receive pointer to any symbols that reference
* one of the input sections being merged.
* reloc_list - List of relocation descriptors to examine.
* Either ofl->&ofl->ofl_actrels (active relocations)
* or &ofl->ofl_outrels (output relocations).
*
* exit:
* On success, rel_aplist and sym_aplist are updated, and
* any strings in the mergable 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;
/* LINTED */
(FLG_IS_DISCARD | FLG_IS_INSTRMRG)) !=
FLG_IS_INSTRMRG) ||
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.
*/
AL_CNT_STRMRGSYM) == 0)
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.
*/
STT_SECTION) &&
AL_CNT_STRMRGREL) == 0))
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_aplist, sym_aplist, - 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_aplist and sym_aplist 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
APlist **sym_aplist)
{
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 mergable 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.
*/
/*
* Change the descriptor name to reflect the fact that it
* points at 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);
}
/*
* 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);
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);
}
/*
* 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_aplist and sym_aplist 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 allocatated
* for this processing for all the output sections.
*/
int error_seen = 0;
&rel_aplist, &sym_aplist) ==
S_ERROR)) {
error_seen = 1;
break;
}
}
if (rel_aplist != NULL)
if (sym_aplist != NULL)
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);
return (S_ERROR);
/*
* There is no use for .hash and .dynsym sections in a
* relocatable object.
*/
if (!(flags & FLG_OF_RELOBJ)) {
return (S_ERROR);
return (S_ERROR);
#if defined(_ELF64)
return (S_ERROR);
#endif
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 of our sections adjust the size
* of SHT_SUNW_versym & SHT_SUNW_syminfo which are dependent on
* the symbol table sizes.
*/
} else {
}
if (ofl->ofl_osversym) {
}
if (ofl->ofl_ossyminfo) {
}
}
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.
*/
return (isec);
}