blob: 8df2a57e0dbe2b7d6e7373ffc7578e83ffa3b838 [file] [log] [blame]
/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2001.
Red Hat elfutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
Free Software Foundation; version 2 of the License.
Red Hat elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with Red Hat elfutils; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Red Hat elfutils is an included package of the Open Invention Network.
An included package of the Open Invention Network is a package for which
Open Invention Network licensees cross-license their patents. No patent
license is granted, either expressly or impliedly, by designation as an
included package. Should you wish to participate in the Open Invention
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <ctype.h>
#include <dlfcn.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <gelf.h>
#include <inttypes.h>
#include <libintl.h>
#include <stdbool.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <elf-knowledge.h>
#include "ld.h"
#include "list.h"
#include <md5.h>
#include <sha1.h>
#include <system.h>
/* Header of .eh_frame_hdr section. */
struct unw_eh_frame_hdr
{
unsigned char version;
unsigned char eh_frame_ptr_enc;
unsigned char fde_count_enc;
unsigned char table_enc;
};
#define EH_FRAME_HDR_VERSION 1
/* Prototypes for local functions. */
static const char **ld_generic_lib_extensions (struct ld_state *)
__attribute__ ((__const__));
static int ld_generic_file_close (struct usedfiles *fileinfo,
struct ld_state *statep);
static int ld_generic_file_process (int fd, struct usedfiles *fileinfo,
struct ld_state *statep,
struct usedfiles **nextp);
static void ld_generic_generate_sections (struct ld_state *statep);
static void ld_generic_create_sections (struct ld_state *statep);
static int ld_generic_flag_unresolved (struct ld_state *statep);
static int ld_generic_open_outfile (struct ld_state *statep, int machine,
int class, int data);
static int ld_generic_create_outfile (struct ld_state *statep);
static void ld_generic_relocate_section (struct ld_state *statep,
Elf_Scn *outscn,
struct scninfo *firstp,
const Elf32_Word *dblindirect);
static int ld_generic_finalize (struct ld_state *statep);
static bool ld_generic_special_section_number_p (struct ld_state *statep,
size_t number);
static bool ld_generic_section_type_p (struct ld_state *statep,
XElf_Word type);
static XElf_Xword ld_generic_dynamic_section_flags (struct ld_state *statep);
static void ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn);
static void ld_generic_initialize_pltrel (struct ld_state *statep,
Elf_Scn *scn);
static void ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn);
static void ld_generic_initialize_gotplt (struct ld_state *statep,
Elf_Scn *scn);
static void ld_generic_finalize_plt (struct ld_state *statep, size_t nsym,
size_t nsym_dyn,
struct symbol **ndxtosymp);
static int ld_generic_rel_type (struct ld_state *statep);
static void ld_generic_count_relocations (struct ld_state *statep,
struct scninfo *scninfo);
static void ld_generic_create_relocations (struct ld_state *statep,
const Elf32_Word *dblindirect);
static int file_process2 (struct usedfiles *fileinfo);
static void mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
struct scninfo **grpscnp);
/* Map symbol index to struct symbol record. */
static struct symbol **ndxtosym;
/* String table reference to all symbols in the symbol table. */
static struct Ebl_Strent **symstrent;
/* Check whether file associated with FD is a DSO. */
static bool
is_dso_p (int fd)
{
/* We have to read the 'e_type' field. It has the same size (16
bits) in 32- and 64-bit ELF. */
XElf_Half e_type;
return (pread (fd, &e_type, sizeof (e_type), offsetof (XElf_Ehdr, e_type))
== sizeof (e_type)
&& e_type == ET_DYN);
}
/* Print the complete name of a file, including the archive it is
contained in. */
static int
print_file_name (FILE *s, struct usedfiles *fileinfo, int first_level,
int newline)
{
int npar = 0;
if (fileinfo->archive_file != NULL)
{
npar = print_file_name (s, fileinfo->archive_file, 0, 0) + 1;
fputc_unlocked ('(', s);
fputs_unlocked (fileinfo->rfname, s);
if (first_level)
while (npar-- > 0)
fputc_unlocked (')', s);
}
else
fputs_unlocked (fileinfo->rfname, s);
if (first_level && newline)
fputc_unlocked ('\n', s);
return npar;
}
/* Function to determine whether an object will be dynamically linked. */
bool
dynamically_linked_p (void)
{
return (ld_state.file_type == dso_file_type || ld_state.nplt > 0
|| ld_state.ngot > 0);
}
bool
linked_from_dso_p (struct scninfo *scninfo, size_t symidx)
{
struct usedfiles *file = scninfo->fileinfo;
/* If this symbol is not undefined in this file it cannot come from
a DSO. */
if (symidx < file->nlocalsymbols)
return false;
struct symbol *sym = file->symref[symidx];
return sym->defined && sym->in_dso;
}
/* Initialize state object. This callback function is called after the
parameters are parsed but before any file is searched for. */
int
ld_prepare_state (const char *emulation)
{
/* When generating DSO we normally allow undefined symbols. */
ld_state.nodefs = true;
/* To be able to detect problems we add a .comment section entry by
default. */
ld_state.add_ld_comment = true;
/* XXX We probably should find a better place for this. The index
of the first user-defined version is 2. */
ld_state.nextveridx = 2;
/* Pick an not too small number for the initial size of the tables. */
ld_symbol_tab_init (&ld_state.symbol_tab, 1027);
ld_section_tab_init (&ld_state.section_tab, 67);
ld_version_str_tab_init (&ld_state.version_str_tab, 67);
/* Initialize the section header string table. */
ld_state.shstrtab = ebl_strtabinit (true);
if (ld_state.shstrtab == NULL)
error (EXIT_FAILURE, errno, gettext ("cannot create string table"));
/* Initialize the callbacks. These are the defaults, the appropriate
backend can later install its own callbacks. */
ld_state.callbacks.lib_extensions = ld_generic_lib_extensions;
ld_state.callbacks.file_process = ld_generic_file_process;
ld_state.callbacks.file_close = ld_generic_file_close;
ld_state.callbacks.generate_sections = ld_generic_generate_sections;
ld_state.callbacks.create_sections = ld_generic_create_sections;
ld_state.callbacks.flag_unresolved = ld_generic_flag_unresolved;
ld_state.callbacks.open_outfile = ld_generic_open_outfile;
ld_state.callbacks.create_outfile = ld_generic_create_outfile;
ld_state.callbacks.relocate_section = ld_generic_relocate_section;
ld_state.callbacks.finalize = ld_generic_finalize;
ld_state.callbacks.special_section_number_p =
ld_generic_special_section_number_p;
ld_state.callbacks.section_type_p = ld_generic_section_type_p;
ld_state.callbacks.dynamic_section_flags = ld_generic_dynamic_section_flags;
ld_state.callbacks.initialize_plt = ld_generic_initialize_plt;
ld_state.callbacks.initialize_pltrel = ld_generic_initialize_pltrel;
ld_state.callbacks.initialize_got = ld_generic_initialize_got;
ld_state.callbacks.initialize_gotplt = ld_generic_initialize_gotplt;
ld_state.callbacks.finalize_plt = ld_generic_finalize_plt;
ld_state.callbacks.rel_type = ld_generic_rel_type;
ld_state.callbacks.count_relocations = ld_generic_count_relocations;
ld_state.callbacks.create_relocations = ld_generic_create_relocations;
#ifndef BASE_ELF_NAME
/* Find the ld backend library. Use EBL to determine the name if
the user hasn't provided one on the command line. */
if (emulation == NULL)
{
emulation = ebl_backend_name (ld_state.ebl);
assert (emulation != NULL);
}
size_t emulation_len = strlen (emulation);
/* Construct the file name. */
char *fname = (char *) alloca (sizeof "libld_" - 1 + emulation_len
+ sizeof ".so");
strcpy (mempcpy (stpcpy (fname, "libld_"), emulation, emulation_len), ".so");
/* Try loading. */
void *h = dlopen (fname, RTLD_LAZY);
if (h == NULL)
error (EXIT_FAILURE, 0,
gettext ("cannot load ld backend library '%s': %s"),
fname, dlerror ());
/* Find the initializer. It must be present. */
char *initname = (char *) alloca (emulation_len + sizeof "_ld_init");
strcpy (mempcpy (initname, emulation, emulation_len), "_ld_init");
int (*initfct) (struct ld_state *)
= (int (*) (struct ld_state *)) dlsym (h, initname);
if (initfct == NULL)
error (EXIT_FAILURE, 0, gettext ("\
cannot find init function in ld backend library '%s': %s"),
fname, dlerror ());
/* Store the handle. */
ld_state.ldlib = h;
/* Call the init function. */
return initfct (&ld_state);
#else
# define INIT_FCT_NAME(base) _INIT_FCT_NAME(base)
# define _INIT_FCT_NAME(base) base##_ld_init
/* Declare and call the initialization function. */
extern int INIT_FCT_NAME(BASE_ELF_NAME) (struct ld_state *);
return INIT_FCT_NAME(BASE_ELF_NAME) (&ld_state);
#endif
}
static int
check_for_duplicate2 (struct usedfiles *newp, struct usedfiles *list)
{
struct usedfiles *first;
struct usedfiles *prevp;
if (list == NULL)
return 0;
prevp = list;
list = first = list->next;
do
{
/* When searching the needed list we might come across entries
for files which are not yet opened. Stop then, there is
nothing more to test. */
if (likely (list->status == not_opened))
break;
if (unlikely (list->ino == newp->ino)
&& unlikely (list->dev == newp->dev))
{
close (newp->fd);
newp->fd = -1;
newp->status = closed;
if (newp->file_type == relocatable_file_type)
error (0, 0, gettext ("%s listed more than once as input"),
newp->rfname);
return 1;
}
list = list->next;
}
while (likely (list != first));
return 0;
}
static int
check_for_duplicate (struct usedfiles *newp)
{
struct stat st;
if (unlikely (fstat (newp->fd, &st) < 0))
{
close (newp->fd);
return errno;
}
newp->dev = st.st_dev;
newp->ino = st.st_ino;
return (check_for_duplicate2 (newp, ld_state.relfiles)
|| check_for_duplicate2 (newp, ld_state.dsofiles)
|| check_for_duplicate2 (newp, ld_state.needed));
}
/* Find a file along the path described in the state. */
static int
open_along_path2 (struct usedfiles *fileinfo, struct pathelement *path)
{
const char *fname = fileinfo->fname;
size_t fnamelen = strlen (fname);
int err = ENOENT;
struct pathelement *firstp = path;
if (path == NULL)
/* Cannot find anything since we have no path. */
return ENOENT;
do
{
if (likely (path->exist >= 0))
{
/* Create the file name. */
char *rfname = NULL;
size_t dirlen = strlen (path->pname);
int fd = -1;
if (fileinfo->file_type == archive_file_type)
{
const char **exts = (ld_state.statically
? (const char *[2]) { ".a", NULL }
: LIB_EXTENSION (&ld_state));
/* We have to create the actual file name. We prepend "lib"
and add one of the extensions the platform has. */
while (*exts != NULL)
{
size_t extlen = strlen (*exts);
rfname = (char *) alloca (dirlen + 5 + fnamelen + extlen);
memcpy (mempcpy (stpcpy (mempcpy (rfname, path->pname,
dirlen),
"/lib"),
fname, fnamelen),
*exts, extlen + 1);
fd = open (rfname, O_RDONLY);
if (likely (fd != -1) || errno != ENOENT)
{
err = fd == -1 ? errno : 0;
break;
}
/* Next extension. */
++exts;
}
}
else
{
assert (fileinfo->file_type == dso_file_type
|| fileinfo->file_type == dso_needed_file_type);
rfname = (char *) alloca (dirlen + 1 + fnamelen + 1);
memcpy (stpcpy (mempcpy (rfname, path->pname, dirlen), "/"),
fname, fnamelen + 1);
fd = open (rfname, O_RDONLY);
if (unlikely (fd == -1))
err = errno;
}
if (likely (fd != -1))
{
/* We found the file. This also means the directory
exists. */
fileinfo->fd = fd;
path->exist = 1;
/* Check whether we have this file already loaded. */
if (unlikely (check_for_duplicate (fileinfo) != 0))
return EAGAIN;
/* Make a copy of the name. */
fileinfo->rfname = obstack_strdup (&ld_state.smem, rfname);
if (unlikely (ld_state.trace_files))
printf (fileinfo->file_type == archive_file_type
? gettext ("%s (for -l%s)\n")
: gettext ("%s (for DT_NEEDED %s)\n"),
rfname, fname);
return 0;
}
/* The file does not exist. Maybe the whole directory doesn't.
Check it unless we know it exists. */
if (unlikely (path->exist == 0))
{
struct stat st;
/* Keep only the directory name. Note that the path
might be relative. This doesn't matter here. We do
the test in any case even if there is the chance that
somebody wants to change the programs working
directory at some point which would make the result
of this test void. Since changing the working
directory is completely wrong we are not taking this
case into account. */
rfname[dirlen] = '\0';
if (unlikely (stat (rfname, &st) < 0) || ! S_ISDIR (st.st_mode))
/* The directory does not exist or the named file is no
directory. */
path->exist = -1;
else
path->exist = 1;
}
}
/* Next path element. */
path = path->next;
}
while (likely (err == ENOENT && path != firstp));
return err;
}
static int
open_along_path (struct usedfiles *fileinfo)
{
const char *fname = fileinfo->fname;
int err = ENOENT;
if (fileinfo->file_type == relocatable_file_type)
{
/* Only libraries are searched along the path. */
fileinfo->fd = open (fname, O_RDONLY);
if (likely (fileinfo->fd != -1))
{
/* We found the file. */
if (unlikely (ld_state.trace_files))
print_file_name (stdout, fileinfo, 1, 1);
return check_for_duplicate (fileinfo);
}
/* If the name is an absolute path we are done. */
err = errno;
}
else
{
/* If the user specified two parts to the LD_LIBRARY_PATH variable
try the first part now. */
err = open_along_path2 (fileinfo, ld_state.ld_library_path1);
/* Try the user-specified path next. */
if (err == ENOENT)
err = open_along_path2 (fileinfo,
fileinfo->file_type == archive_file_type
? ld_state.paths : ld_state.rpath_link);
/* Then the second part of the LD_LIBRARY_PATH value. */
if (unlikely (err == ENOENT))
{
err = open_along_path2 (fileinfo, ld_state.ld_library_path2);
/* In case we look for a DSO handle now the RUNPATH. */
if (err == ENOENT)
{
if (fileinfo->file_type == dso_file_type)
err = open_along_path2 (fileinfo, ld_state.runpath_link);
/* Finally the path from the default linker script. */
if (err == ENOENT)
err = open_along_path2 (fileinfo, ld_state.default_paths);
}
}
}
if (unlikely (err != 0)
&& (err != EAGAIN || fileinfo->file_type == relocatable_file_type))
error (0, err, gettext ("cannot open %s"), fileinfo->fname);
return err;
}
static int
matching_group_comdat_scn (const XElf_Sym *sym, size_t shndx,
struct usedfiles *fileinfo, struct symbol *oldp)
{
if ((shndx >= SHN_LORESERVE && shndx <= SHN_HIRESERVE)
|| (oldp->scndx >= SHN_LORESERVE && oldp->scndx <= SHN_HIRESERVE))
/* Cannot be a group COMDAT section. */
return 0;
size_t newgrpid = fileinfo->scninfo[shndx].grpid;
size_t oldgrpid = oldp->file->scninfo[oldp->scndx].grpid;
if (newgrpid == 0 || oldgrpid == 0)
return 0;
assert (SCNINFO_SHDR (fileinfo->scninfo[newgrpid].shdr).sh_type
== SHT_GROUP);
assert (SCNINFO_SHDR (oldp->file->scninfo[oldgrpid].shdr).sh_type
== SHT_GROUP);
if (! fileinfo->scninfo[newgrpid].comdat_group
|| ! oldp->file->scninfo[oldgrpid].comdat_group)
return 0;
if (strcmp (fileinfo->scninfo[newgrpid].symbols->name,
oldp->file->scninfo[oldgrpid].symbols->name) != 0)
return 0;
/* This is a matching, duplicate COMDAT group section. Ignore it. */
return 1;
}
static void
check_type_and_size (const XElf_Sym *sym, struct usedfiles *fileinfo,
struct symbol *oldp)
{
/* We check the type and size of the symbols. In both cases the
information can be missing (size is zero, type is STT_NOTYPE) in
which case we issue no warnings. Otherwise everything must
match. If the type does not match there is no point in checking
the size. */
if (XELF_ST_TYPE (sym->st_info) != STT_NOTYPE && oldp->type != STT_NOTYPE
&& unlikely (oldp->type != XELF_ST_TYPE (sym->st_info)))
{
char buf1[64];
char buf2[64];
error (0, 0, gettext ("\
Warning: type of `%s' changed from %s in %s to %s in %s"),
oldp->name,
ebl_symbol_type_name (ld_state.ebl, oldp->type,
buf1, sizeof (buf1)),
oldp->file->rfname,
ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
buf2, sizeof (buf2)),
fileinfo->rfname);
}
else if (XELF_ST_TYPE (sym->st_info) == STT_OBJECT
&& oldp->size != 0
&& unlikely (oldp->size != sym->st_size))
error (0, 0, gettext ("\
Warning: size of `%s' changed from %" PRIu64 " in %s to %" PRIu64 " in %s"),
oldp->name, (uint64_t) oldp->size, oldp->file->rfname,
(uint64_t) sym->st_size, fileinfo->rfname);
}
static int
check_definition (const XElf_Sym *sym, size_t shndx, size_t symidx,
struct usedfiles *fileinfo, struct symbol *oldp)
{
int result = 0;
bool old_in_dso = FILEINFO_EHDR (oldp->file->ehdr).e_type == ET_DYN;
bool new_in_dso = FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN;
bool use_new_def = false;
if (shndx != SHN_UNDEF
&& (! oldp->defined
|| (shndx != SHN_COMMON && oldp->common && ! new_in_dso)
|| (old_in_dso && ! new_in_dso)))
{
/* We found a definition for a previously undefined symbol or a
real definition for a previous common-only definition or a
redefinition of a symbol definition in an object file
previously defined in a DSO. First perform some tests which
will show whether the common is really matching the
definition. */
check_type_and_size (sym, fileinfo, oldp);
/* We leave the next element intact to not interrupt the list
with the unresolved symbols. Whoever walks the list will
have to check the `defined' flag. But we remember that this
list element is not unresolved anymore. */
if (! oldp->defined)
{
/* Remove from the list. */
--ld_state.nunresolved;
if (! oldp->weak)
--ld_state.nunresolved_nonweak;
CDBL_LIST_DEL (ld_state.unresolved, oldp);
}
else if (oldp->common)
/* Remove from the list. */
CDBL_LIST_DEL (ld_state.common_syms, oldp);
/* Use the values of the definition from now on. */
use_new_def = true;
}
else if (shndx != SHN_UNDEF
&& oldp->defined
&& matching_group_comdat_scn (sym, shndx, fileinfo, oldp))
/* The duplicate symbol is in a group COMDAT section with the same
signature as the one containing the original definition.
Just ignore the second definition. */
/* nothing */;
else if (shndx != SHN_UNDEF
&& unlikely (! oldp->common)
&& oldp->defined
&& shndx != SHN_COMMON
/* Multiple definitions are no fatal errors if the -z muldefs flag
is used. We don't warn about the multiple definition unless we
are told to be verbose. */
&& (!ld_state.muldefs || verbose)
&& ! old_in_dso && fileinfo->file_type == relocatable_file_type)
{
/* We have a double definition. This is a problem. */
char buf[64];
XElf_Sym_vardef (oldsym);
struct usedfiles *oldfile;
const char *scnname;
Elf32_Word xndx;
size_t shnum;
if (elf_getshnum (fileinfo->elf, &shnum) < 0)
error (EXIT_FAILURE, 0,
gettext ("cannot determine number of sections: %s"),
elf_errmsg (-1));
/* XXX Use only ebl_section_name. */
if (shndx < SHN_LORESERVE || (shndx > SHN_HIRESERVE && shndx < shnum))
scnname = elf_strptr (fileinfo->elf,
fileinfo->shstrndx,
SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_name);
else
// XXX extended section
scnname = ebl_section_name (ld_state.ebl, shndx, 0, buf, sizeof (buf),
NULL, shnum);
/* XXX Print source file and line number. */
print_file_name (stderr, fileinfo, 1, 0);
fprintf (stderr,
gettext ("(%s+%#" PRIx64 "): multiple definition of %s `%s'\n"),
scnname,
(uint64_t) sym->st_value,
ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
buf, sizeof (buf)),
oldp->name);
oldfile = oldp->file;
xelf_getsymshndx (oldfile->symtabdata, oldfile->xndxdata, oldp->symidx,
oldsym, xndx);
assert (oldsym != NULL);
/* XXX Use only ebl_section_name. */
if (oldp->scndx < SHN_LORESERVE || oldp->scndx > SHN_HIRESERVE)
scnname = elf_strptr (oldfile->elf,
oldfile->shstrndx,
SCNINFO_SHDR (oldfile->scninfo[shndx].shdr).sh_name);
else
scnname = ebl_section_name (ld_state.ebl, oldp->scndx, oldp->scndx,
buf, sizeof (buf), NULL, shnum);
/* XXX Print source file and line number. */
print_file_name (stderr, oldfile, 1, 0);
fprintf (stderr, gettext ("(%s+%#" PRIx64 "): first defined here\n"),
scnname, (uint64_t) oldsym->st_value);
if (likely (!ld_state.muldefs))
result = 1;
}
else if (old_in_dso && fileinfo->file_type == relocatable_file_type
&& shndx != SHN_UNDEF)
/* We use the definition from a normal relocatable file over the
definition in a DSO. This is what the dynamic linker would
do, too. */
use_new_def = true;
else if (old_in_dso && !new_in_dso && oldp->defined && !oldp->on_dsolist)
{
CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
++ld_state.nfrom_dso;
/* If the object is a function we allocate a PLT entry,
otherwise only a GOT entry. */
if (oldp->type == STT_FUNC)
++ld_state.nplt;
else
++ld_state.ngot;
oldp->on_dsolist = 1;
}
else if (oldp->common && shndx == SHN_COMMON)
{
/* The symbol size is the largest of all common definitions. */
oldp->size = MAX (oldp->size, sym->st_size);
/* Similarly for the alignment. */
oldp->merge.value = MAX (oldp->merge.value, sym->st_value);
}
if (unlikely (use_new_def))
{
/* Adjust the symbol record appropriately and remove
the symbol from the list of symbols which are taken from DSOs. */
if (old_in_dso && fileinfo->file_type == relocatable_file_type)
{
CDBL_LIST_DEL (ld_state.from_dso, oldp);
--ld_state.nfrom_dso;
if (likely (oldp->type == STT_FUNC))
--ld_state.nplt;
else
--ld_state.ngot;
oldp->on_dsolist = 0;
}
/* Use the values of the definition from now on. */
oldp->size = sym->st_size;
oldp->type = XELF_ST_TYPE (sym->st_info);
oldp->symidx = symidx;
oldp->scndx = shndx;
//oldp->symscndx = THESYMSCNDX must be passed;
oldp->file = fileinfo;
oldp->defined = 1;
oldp->in_dso = new_in_dso;
oldp->common = shndx == SHN_COMMON;
if (likely (fileinfo->file_type == relocatable_file_type))
{
/* If the definition comes from a DSO we pertain the weak flag
and it's indicating whether the reference is weak or not. */
oldp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
// XXX Really exclude SHN_ABS?
if (shndx != SHN_COMMON && shndx != SHN_ABS)
{
struct scninfo *ignore;
mark_section_used (&fileinfo->scninfo[shndx], shndx, &ignore);
}
}
/* Add to the list of symbols used from DSOs if necessary. */
if (new_in_dso && !old_in_dso)
{
CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
++ld_state.nfrom_dso;
/* If the object is a function we allocate a PLT entry,
otherwise only a GOT entry. */
if (oldp->type == STT_FUNC)
++ld_state.nplt;
else
++ld_state.ngot;
oldp->on_dsolist = 1;
}
else if (shndx == SHN_COMMON)
{
/* Store the alignment. */
oldp->merge.value = sym->st_value;
CDBL_LIST_ADD_REAR (ld_state.common_syms, oldp);
}
}
return result;
}
static struct scninfo *
find_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
Elf_Data **datap)
{
struct scninfo *runp;
for (runp = fileinfo->groups; runp != NULL; runp = runp->next)
if (!runp->used)
{
Elf32_Word *grpref;
size_t cnt;
Elf_Data *data;
data = elf_getdata (runp->scn, NULL);
if (data == NULL)
error (EXIT_FAILURE, 0,
gettext ("%s: cannot get section group data: %s"),
fileinfo->fname, elf_errmsg (-1));
/* There cannot be another data block. */
assert (elf_getdata (runp->scn, data) == NULL);
grpref = (Elf32_Word *) data->d_buf;
cnt = data->d_size / sizeof (Elf32_Word);
/* Note that we stop after looking at index 1 since index 0
contains the flags for the section group. */
while (cnt > 1)
if (grpref[--cnt] == shndx)
{
*datap = data;
return runp;
}
}
/* If we come here no section group contained the given section
despite the SHF_GROUP flag. This is an error in the input
file. */
error (EXIT_FAILURE, 0, gettext ("\
%s: section '%s' with group flag set does not belong to any group"),
fileinfo->fname,
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_name));
return NULL;
}
/* Mark all sections which belong to the same group as section SHNDX
as used. */
static void
mark_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
struct scninfo **grpscnp)
{
/* First locate the section group. There can be several (many) of
them. */
size_t cnt;
Elf32_Word *grpref;
Elf_Data *data;
struct scninfo *grpscn = find_section_group (fileinfo, shndx, &data);
*grpscnp = grpscn;
/* Mark all the sections as used.
XXX Two possible problems here:
- the gABI says "The section must be referenced by a section of type
SHT_GROUP". I hope everybody reads this as "exactly one section".
- section groups are also useful to mark the debugging section which
belongs to a text section. Unconditionally adding debugging sections
is therefore probably not what is wanted if stripping is required. */
/* Mark the section group as handled. */
grpscn->used = true;
grpref = (Elf32_Word *) data->d_buf;
cnt = data->d_size / sizeof (Elf32_Word);
while (cnt > 1)
{
Elf32_Word idx = grpref[--cnt];
XElf_Shdr *shdr = &SCNINFO_SHDR (fileinfo->scninfo[idx].shdr);
if (fileinfo->scninfo[idx].grpid != grpscn->grpid)
error (EXIT_FAILURE, 0, gettext ("\
%s: section [%2d] '%s' is not in the correct section group"),
fileinfo->fname, (int) idx,
elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name));
if (ld_state.strip == strip_none
/* If we are stripping, remove debug sections. */
|| (!ebl_debugscn_p (ld_state.ebl,
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name))
/* And the relocation sections for the debug sections. */
&& ((shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
|| !ebl_debugscn_p (ld_state.ebl,
elf_strptr (fileinfo->elf,
fileinfo->shstrndx,
SCNINFO_SHDR (fileinfo->scninfo[shdr->sh_info].shdr).sh_name)))))
{
struct scninfo *ignore;
mark_section_used (&fileinfo->scninfo[idx], idx, &ignore);
}
}
}
static void
mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
struct scninfo **grpscnp)
{
if (likely (scninfo->used))
/* Nothing to be done. */
return;
/* We need this section. */
scninfo->used = true;
/* Make sure the section header has been read from the file. */
XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
#if NATIVE_ELF
if (unlikely (scninfo->shdr == NULL))
#else
if (unlikely (scninfo->shdr.sh_type == SHT_NULL))
#endif
{
#if NATIVE_ELF != 0
shdr = xelf_getshdr (scninfo->scn, scninfo->shdr);
#else
xelf_getshdr_copy (scninfo->scn, shdr, scninfo->shdr);
#endif
if (unlikely (shdr == NULL))
/* Something is very wrong. The calling code will notice it
soon and print a message. */
return;
}
/* Handle section linked by 'sh_link'. */
if (unlikely (shdr->sh_link != 0))
{
struct scninfo *ignore;
mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_link],
shdr->sh_link, &ignore);
}
/* Handle section linked by 'sh_info'. */
if (unlikely (shdr->sh_info != 0) && (shdr->sh_flags & SHF_INFO_LINK))
{
struct scninfo *ignore;
mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_info],
shdr->sh_info, &ignore);
}
if (unlikely (shdr->sh_flags & SHF_GROUP) && ld_state.gc_sections)
/* Find the section group which contains this section. */
mark_section_group (scninfo->fileinfo, shndx, grpscnp);
}
/* We collect all sections in a hashing table. All sections with the
same name are collected in a list. Note that we do not determine
which sections are finally collected in the same output section
here. This would be terribly inefficient. It will be done later. */
static void
add_section (struct usedfiles *fileinfo, struct scninfo *scninfo)
{
struct scnhead *queued;
struct scnhead search;
unsigned long int hval;
XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
struct scninfo *grpscn = NULL;
Elf_Data *grpscndata = NULL;
/* See whether we can determine right away whether we need this
section in the output.
XXX I assume here that --gc-sections only affects extraction
from an archive. If it also affects objects files given on
the command line then somebody must explain to me how the
dependency analysis should work. Should the entry point be
the root? What if it is a numeric value? */
if (!scninfo->used
&& (ld_state.strip == strip_none
|| (shdr->sh_flags & SHF_ALLOC) != 0
|| shdr->sh_type == SHT_NOTE
|| (shdr->sh_type == SHT_PROGBITS
&& strcmp (elf_strptr (fileinfo->elf,
fileinfo->shstrndx,
shdr->sh_name), ".comment") == 0))
&& (fileinfo->status != in_archive || !ld_state.gc_sections))
/* Mark as used and handle reference recursively if necessary. */
mark_section_used (scninfo, elf_ndxscn (scninfo->scn), &grpscn);
if ((shdr->sh_flags & SHF_GROUP) && grpscn == NULL)
/* Determine the symbol which name constitutes the signature
for the section group. */
grpscn = find_section_group (fileinfo, elf_ndxscn (scninfo->scn),
&grpscndata);
assert (grpscn == NULL || grpscn->symbols->name != NULL);
/* Determine the section name. */
search.name = elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name);
search.type = shdr->sh_type;
search.flags = shdr->sh_flags;
search.entsize = shdr->sh_entsize;
search.grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
search.kind = scn_normal;
hval = elf_hash (search.name);
/* Find already queued sections. */
queued = ld_section_tab_find (&ld_state.section_tab, hval, &search);
if (queued != NULL)
{
bool is_comdat = false;
/* If this section is part of a COMDAT section group we simply
ignore it since we already have a copy. */
if (unlikely (shdr->sh_flags & SHF_GROUP))
{
/* Get the data of the section group section. */
if (grpscndata == NULL)
{
grpscndata = elf_getdata (grpscn->scn, NULL);
assert (grpscndata != NULL);
}
/* XXX Possibly unaligned memory access. */
if ((((Elf32_Word *) grpscndata->d_buf)[0] & GRP_COMDAT) != 0)
{
/* We have to compare the group signatures. There might
be sections with the same name but belonging to
groups with different signatures. This means we have
to compare the new group signature with all those
already collected. There might also be some
non-group sections in the mix. */
struct scninfo *runp = queued->last;
do
{
if (SCNINFO_SHDR (runp->shdr).sh_flags & SHF_GROUP)
{
struct scninfo *grpscn2
= find_section_group (runp->fileinfo,
elf_ndxscn (runp->scn),
&grpscndata);
if (strcmp (grpscn->symbols->name,
grpscn2->symbols->name) == 0)
{
scninfo->unused_comdat = is_comdat = true;
break;
}
}
runp = runp->next;
}
while (runp != queued->last);
}
}
if (!is_comdat)
{
/* No COMDAT section, we use the data. */
scninfo->next = queued->last->next;
queued->last = queued->last->next = scninfo;
queued->flags = ebl_sh_flags_combine (ld_state.ebl, queued->flags,
shdr->sh_flags);
queued->align = MAX (queued->align, shdr->sh_addralign);
}
}
else
{
/* We do not use obstacks here since the memory might be
deallocated. */
queued = (struct scnhead *) xcalloc (sizeof (struct scnhead), 1);
queued->kind = scn_normal;
queued->name = search.name;
queued->type = shdr->sh_type;
queued->flags = shdr->sh_flags;
queued->align = shdr->sh_addralign;
queued->entsize = shdr->sh_entsize;
queued->grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
queued->segment_nr = ~0;
queued->last = scninfo->next = scninfo;
/* Check whether we need a TLS segment. */
ld_state.need_tls |= (shdr->sh_flags & SHF_TLS) != 0;
/* Add to the hash table and possibly overwrite existing value. */
ld_section_tab_insert (&ld_state.section_tab, hval, queued);
}
}
static int
add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype)
{
size_t scncnt;
size_t cnt;
Elf_Data *symtabdata = NULL;
Elf_Data *xndxdata = NULL;
Elf_Data *versymdata = NULL;
Elf_Data *verdefdata = NULL;
Elf_Data *verneeddata = NULL;
size_t symstridx = 0;
size_t nsymbols = 0;
size_t nlocalsymbols = 0;
bool has_merge_sections = false;
bool has_tls_symbols = false;
/* Unless we have different information we assume the code needs
an executable stack. */
enum execstack execstack = execstack_true;
/* Prerequisites. */
assert (fileinfo->elf != NULL);
/* Allocate memory for the sections. */
if (unlikely (elf_getshnum (fileinfo->elf, &scncnt) < 0))
error (EXIT_FAILURE, 0,
gettext ("cannot determine number of sections: %s"),
elf_errmsg (-1));
fileinfo->scninfo = (struct scninfo *)
obstack_calloc (&ld_state.smem, scncnt * sizeof (struct scninfo));
/* Read all the section headers and find the symbol table. Note
that we don't skip the section with index zero. Even though the
section itself is always empty the section header contains
informaton for the case when the section index for the section
header string table is too large to fit in the ELF header. */
for (cnt = 0; cnt < scncnt; ++cnt)
{
/* Store the handle for the section. */
fileinfo->scninfo[cnt].scn = elf_getscn (fileinfo->elf, cnt);
/* Get the ELF section header and data. */
XElf_Shdr *shdr;
#if NATIVE_ELF != 0
if (fileinfo->scninfo[cnt].shdr == NULL)
#else
if (fileinfo->scninfo[cnt].shdr.sh_type == SHT_NULL)
#endif
{
#if NATIVE_ELF != 0
shdr = xelf_getshdr (fileinfo->scninfo[cnt].scn,
fileinfo->scninfo[cnt].shdr);
#else
xelf_getshdr_copy (fileinfo->scninfo[cnt].scn, shdr,
fileinfo->scninfo[cnt].shdr);
#endif
if (shdr == NULL)
{
/* This should never happen. */
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
}
else
shdr = &SCNINFO_SHDR (fileinfo->scninfo[cnt].shdr);
Elf_Data *data = elf_getdata (fileinfo->scninfo[cnt].scn, NULL);
/* Check whether this section is marked as merge-able. */
has_merge_sections |= (shdr->sh_flags & SHF_MERGE) != 0;
has_tls_symbols |= (shdr->sh_flags & SHF_TLS) != 0;
/* Get the ELF section header and data. */
/* Make the file structure available. */
fileinfo->scninfo[cnt].fileinfo = fileinfo;
if (unlikely (shdr->sh_type == SHT_SYMTAB)
|| unlikely (shdr->sh_type == SHT_DYNSYM))
{
if (shdr->sh_type == SHT_SYMTAB)
{
assert (fileinfo->symtabdata == NULL);
fileinfo->symtabdata = data;
fileinfo->nsymtab = shdr->sh_size / shdr->sh_entsize;
fileinfo->nlocalsymbols = shdr->sh_info;
fileinfo->symstridx = shdr->sh_link;
}
else
{
assert (fileinfo->dynsymtabdata == NULL);
fileinfo->dynsymtabdata = data;
fileinfo->ndynsymtab = shdr->sh_size / shdr->sh_entsize;
fileinfo->dynsymstridx = shdr->sh_link;
}
/* If we are looking for the normal symbol table we just
found it. */
if (secttype == shdr->sh_type)
{
assert (symtabdata == NULL);
symtabdata = data;
symstridx = shdr->sh_link;
nsymbols = shdr->sh_size / shdr->sh_entsize;
nlocalsymbols = shdr->sh_info;
}
}
else if (unlikely (shdr->sh_type == SHT_SYMTAB_SHNDX))
{
assert (xndxdata == NULL);
fileinfo->xndxdata = xndxdata = data;
}
else if (unlikely (shdr->sh_type == SHT_GNU_versym))
{
assert (versymdata == 0);
fileinfo->versymdata = versymdata = data;
}
else if (unlikely (shdr->sh_type == SHT_GNU_verdef))
{
size_t nversions;
assert (verdefdata == 0);
fileinfo->verdefdata = verdefdata = data;
/* Allocate the arrays flagging the use of the version and
to track of allocated names. */
fileinfo->nverdef = nversions = shdr->sh_info;
/* We have NVERSIONS + 1 because the indeces used to access the
sectino start with one; zero represents local binding. */
fileinfo->verdefused = (XElf_Versym *)
obstack_calloc (&ld_state.smem,
sizeof (XElf_Versym) * (nversions + 1));
fileinfo->verdefent = (struct Ebl_Strent **)
obstack_alloc (&ld_state.smem,
sizeof (struct Ebl_Strent *) * (nversions + 1));
}
else if (unlikely (shdr->sh_type == SHT_GNU_verneed))
{
assert (verneeddata == 0);
fileinfo->verneeddata = verneeddata = data;
}
else if (unlikely (shdr->sh_type == SHT_DYNAMIC))
{
assert (fileinfo->dynscn == NULL);
fileinfo->dynscn = fileinfo->scninfo[cnt].scn;
}
else if (unlikely (shdr->sh_type == SHT_GROUP))
{
Elf_Scn *symscn;
XElf_Shdr_vardef (symshdr);
Elf_Data *symdata;
if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL)
error (EXIT_FAILURE, 0, gettext ("\
%s: only files of type ET_REL might contain section groups"),
fileinfo->fname);
fileinfo->scninfo[cnt].next = fileinfo->groups;
fileinfo->scninfo[cnt].grpid = cnt;
fileinfo->groups = &fileinfo->scninfo[cnt];
/* Determine the signature. We create a symbol record for
it. Only the name element is important. */
fileinfo->scninfo[cnt].symbols = (struct symbol *)
obstack_calloc (&ld_state.smem, sizeof (struct symbol));
symscn = elf_getscn (fileinfo->elf, shdr->sh_link);
xelf_getshdr (symscn, symshdr);
symdata = elf_getdata (symscn, NULL);
if (symshdr != NULL)
{
XElf_Sym_vardef (sym);
/* We don't need the section index and therefore we don't
have to use 'xelf_getsymshndx'. */
xelf_getsym (symdata, shdr->sh_info, sym);
if (sym != NULL)
{
struct symbol *symbol = fileinfo->scninfo[cnt].symbols;
#ifndef NO_HACKS
if (XELF_ST_TYPE (sym->st_info) == STT_SECTION)
{
XElf_Shdr_vardef (buggyshdr);
xelf_getshdr (elf_getscn (fileinfo->elf, sym->st_shndx),
buggyshdr);
symbol->name = elf_strptr (fileinfo->elf,
FILEINFO_EHDR (fileinfo->ehdr).e_shstrndx,
buggyshdr->sh_name);
symbol->symidx = -1;
}
else
#endif
{
symbol->name = elf_strptr (fileinfo->elf,
symshdr->sh_link,
sym->st_name);
symbol->symidx = shdr->sh_info;
}
symbol->file = fileinfo;
}
}
if (fileinfo->scninfo[cnt].symbols->name == NULL)
error (EXIT_FAILURE, 0, gettext ("\
%s: cannot determine signature of section group [%2zd] '%s': %s"),
fileinfo->fname,
elf_ndxscn (fileinfo->scninfo[cnt].scn),
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name),
elf_errmsg (-1));
/* For all the sections which are part of this group, add
the reference. */
if (data == NULL)
error (EXIT_FAILURE, 0, gettext ("\
%s: cannot get content of section group [%2zd] '%s': %s'"),
fileinfo->fname, elf_ndxscn (fileinfo->scninfo[cnt].scn),
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name),
elf_errmsg (-1));
Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
if (grpdata[0] & GRP_COMDAT)
fileinfo->scninfo[cnt].comdat_group = true;
for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
++inner)
{
if (grpdata[inner] >= scncnt)
error (EXIT_FAILURE, 0, gettext ("\
%s: group member %zu of section group [%2zd] '%s' has too high index: %" PRIu32),
fileinfo->fname,
inner, elf_ndxscn (fileinfo->scninfo[cnt].scn),
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name),
grpdata[inner]);
fileinfo->scninfo[grpdata[inner]].grpid = cnt;
}
/* The 'used' flag is used to indicate when the information
in the section group is used to mark all other sections
as used. So it must not be true yet. */
assert (fileinfo->scninfo[cnt].used == false);
}
else if (! SECTION_TYPE_P (&ld_state, shdr->sh_type)
&& unlikely ((shdr->sh_flags & SHF_OS_NONCONFORMING) != 0))
/* According to the gABI it is a fatal error if the file contains
a section with unknown type and the SHF_OS_NONCONFORMING flag
set. */
error (EXIT_FAILURE, 0,
gettext ("%s: section '%s' has unknown type: %d"),
fileinfo->fname,
elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name),
(int) shdr->sh_type);
/* We don't have to add a few section types here. These will be
generated from scratch for the new output file. We also
don't add the sections of DSOs here since these sections are
not used in the resulting object file. */
else if (likely (fileinfo->file_type == relocatable_file_type)
&& likely (cnt > 0)
&& likely (shdr->sh_type == SHT_PROGBITS
|| shdr->sh_type == SHT_RELA
|| shdr->sh_type == SHT_REL
|| shdr->sh_type == SHT_NOTE
|| shdr->sh_type == SHT_NOBITS
|| shdr->sh_type == SHT_INIT_ARRAY
|| shdr->sh_type == SHT_FINI_ARRAY
|| shdr->sh_type == SHT_PREINIT_ARRAY))
{
/* Check whether the section needs to be executable. */
if (shdr->sh_type == SHT_PROGBITS
&& (shdr->sh_flags & SHF_EXECINSTR) == 0
&& strcmp (elf_strptr (fileinfo->elf, fileinfo->shstrndx,
shdr->sh_name),
".note.GNU-stack") == 0)
execstack = execstack_false;
add_section (fileinfo, &fileinfo->scninfo[cnt]);
}
}
/* Now we know more about the requirements for an executable stack
of the result. */
if (fileinfo->file_type == relocatable_file_type
&& execstack == execstack_true
&& ld_state.execstack != execstack_false_force)
ld_state.execstack = execstack_true;
/* Handle the symbols. Record defined and undefined symbols in the
hash table. In theory there can be a file without any symbol
table. */
if (likely (symtabdata != NULL))
{
/* In case this file contains merge-able sections we have to
locate the symbols which are in these sections. */
fileinfo->has_merge_sections = has_merge_sections;
if (likely (has_merge_sections || has_tls_symbols))
{
fileinfo->symref = (struct symbol **)
obstack_calloc (&ld_state.smem,
nsymbols * sizeof (struct symbol *));
/* Only handle the local symbols here. */
for (cnt = 0; cnt < nlocalsymbols; ++cnt)
{
Elf32_Word shndx;
XElf_Sym_vardef (sym);
xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
if (sym == NULL)
{
/* This should never happen. */
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
if (likely (shndx != SHN_XINDEX))
shndx = sym->st_shndx;
else if (unlikely (shndx == 0))
{
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
if (XELF_ST_TYPE (sym->st_info) != STT_SECTION
&& (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
&& ((SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
& SHF_MERGE)
|| XELF_ST_TYPE (sym->st_info) == STT_TLS))
{
/* Create a symbol record for this symbol and add it
to the list for this section. */
struct symbol *newp;
newp = (struct symbol *)
obstack_calloc (&ld_state.smem, sizeof (struct symbol));
newp->symidx = cnt;
newp->scndx = shndx;
newp->file = fileinfo;
newp->defined = 1;
fileinfo->symref[cnt] = newp;
if (fileinfo->scninfo[shndx].symbols == NULL)
fileinfo->scninfo[shndx].symbols = newp->next_in_scn
= newp;
else
{
newp->next_in_scn
= fileinfo->scninfo[shndx].symbols->next_in_scn;
fileinfo->scninfo[shndx].symbols
= fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
}
}
}
}
else
/* Create array with pointers to the symbol definitions. Note
that we only allocate memory for the non-local symbols
since we have no merge-able sections. But we store the
pointer as if it was for the whole symbol table. This
saves some memory. */
fileinfo->symref = (struct symbol **)
obstack_calloc (&ld_state.smem, ((nsymbols - nlocalsymbols)
* sizeof (struct symbol *)))
- nlocalsymbols;
/* Don't handle local symbols here. It's either not necessary
at all or has already happened. */
for (cnt = nlocalsymbols; cnt < nsymbols; ++cnt)
{
XElf_Sym_vardef (sym);
Elf32_Word shndx;
xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
if (sym == NULL)
{
/* This should never happen. */
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
if (likely (shndx != SHN_XINDEX))
shndx = sym->st_shndx;
else if (unlikely (shndx == 0))
{
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
/* We ignore ABS symbols from DSOs. */
// XXX Is this correct?
if (unlikely (shndx == SHN_ABS) && secttype == SHT_DYNSYM)
continue;
if ((shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
&& fileinfo->scninfo[shndx].unused_comdat)
/* The symbol is not used. */
continue;
/* If the DSO uses symbol versions determine whether this is
the default version. Otherwise we'll ignore the symbol. */
if (versymdata != NULL)
{
XElf_Versym versym;
if (xelf_getversym_copy (versymdata, cnt, versym) == NULL)
/* XXX Should we handle faulty input files more graceful? */
assert (! "xelf_getversym failed");
if ((versym & 0x8000) != 0)
/* Ignore the symbol, it's not the default version. */
continue;
}
/* See whether we know anything about this symbol. */
struct symbol search;
search.name = elf_strptr (fileinfo->elf, symstridx, sym->st_name);
unsigned long int hval = elf_hash (search.name);
/* We ignore the symbols the linker generates. This are
_GLOBAL_OFFSET_TABLE_, _DYNAMIC. */
// XXX This loop is hot and the following tests hardly ever match.
// XXX Maybe move the tests somewhere they are executed less often.
if (((unlikely (hval == 165832675ul)
&& strcmp (search.name, "_DYNAMIC") == 0)
|| (unlikely (hval == 102264335ul)
&& strcmp (search.name, "_GLOBAL_OFFSET_TABLE_") == 0))
&& sym->st_shndx != SHN_UNDEF
/* If somebody defines such a variable in a relocatable we
don't ignore it. Let the user get what s/he deserves. */
&& fileinfo->file_type != relocatable_file_type)
continue;
struct symbol *oldp = ld_symbol_tab_find (&ld_state.symbol_tab,
hval, &search);
struct symbol *newp;
if (likely (oldp == NULL))
{
/* No symbol of this name known. Add it. */
newp = (struct symbol *) obstack_alloc (&ld_state.smem,
sizeof (*newp));
newp->name = search.name;
newp->size = sym->st_size;
newp->type = XELF_ST_TYPE (sym->st_info);
newp->symidx = cnt;
newp->outsymidx = 0;
newp->outdynsymidx = 0;
newp->scndx = shndx;
newp->file = fileinfo;
newp->defined = newp->scndx != SHN_UNDEF;
newp->common = newp->scndx == SHN_COMMON;
newp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
newp->added = 0;
newp->merged = 0;
newp->local = 0;
newp->hidden = 0;
newp->need_copy = 0;
newp->on_dsolist = 0;
newp->in_dso = secttype == SHT_DYNSYM;
newp->next_in_scn = NULL;
#ifndef NDEBUG
newp->next = NULL;
newp->previous = NULL;
#endif
if (newp->scndx == SHN_UNDEF)
{
CDBL_LIST_ADD_REAR (ld_state.unresolved, newp);
++ld_state.nunresolved;
if (! newp->weak)
++ld_state.nunresolved_nonweak;
}
else if (newp->scndx == SHN_COMMON)
{
/* Store the alignment requirement. */
newp->merge.value = sym->st_value;
CDBL_LIST_ADD_REAR (ld_state.common_syms, newp);
}
/* Insert the new symbol. */
if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
hval, newp) != 0))
/* This cannot happen. */
abort ();
fileinfo->symref[cnt] = newp;
/* We have a few special symbols to recognize. The symbols
_init and _fini are the initialization and finalization
functions respectively. They have to be made known in
the dynamic section and therefore we have to find out
now whether these functions exist or not. */
if (hval == 6685956 && strcmp (newp->name, "_init") == 0)
ld_state.init_symbol = newp;
else if (hval == 6672457 && strcmp (newp->name, "_fini") == 0)
ld_state.fini_symbol = newp;
}
else if (unlikely (check_definition (sym, shndx, cnt, fileinfo, oldp)
!= 0))
/* A fatal error (multiple definition of a symbol)
occurred, no need to continue. */
return 1;
else
/* Use the previously allocated symbol record. It has
been updated in check_definition(), if necessary. */
newp = fileinfo->symref[cnt] = oldp;
/* Mark the section the symbol we need comes from as used. */
if (shndx != SHN_UNDEF
&& (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE))
{
struct scninfo *ignore;
#ifndef NDEBUG
size_t shnum;
assert (elf_getshnum (fileinfo->elf, &shnum) == 0);
assert (shndx < shnum);
#endif
/* Mark section (and all dependencies) as used. */
mark_section_used (&fileinfo->scninfo[shndx], shndx, &ignore);
/* Check whether the section is merge-able. In this case we
have to record the symbol. */
if (SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
& SHF_MERGE)
{
if (fileinfo->scninfo[shndx].symbols == NULL)
fileinfo->scninfo[shndx].symbols = newp->next_in_scn
= newp;
else
{
newp->next_in_scn
= fileinfo->scninfo[shndx].symbols->next_in_scn;
fileinfo->scninfo[shndx].symbols
= fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
}
}
}
}
/* This file is used. */
if (likely (fileinfo->file_type == relocatable_file_type))
{
if (unlikely (ld_state.relfiles == NULL))
ld_state.relfiles = fileinfo->next = fileinfo;
else
{
fileinfo->next = ld_state.relfiles->next;
ld_state.relfiles = ld_state.relfiles->next = fileinfo;
}
/* Update some summary information in the state structure. */
ld_state.nsymtab += fileinfo->nsymtab;
ld_state.nlocalsymbols += fileinfo->nlocalsymbols;
}
else if (likely (fileinfo->file_type == dso_file_type))
{
CSNGL_LIST_ADD_REAR (ld_state.dsofiles, fileinfo);
++ld_state.ndsofiles;
if (fileinfo->lazyload)
/* We have to create another dynamic section entry for the
DT_POSFLAG_1 entry.
XXX Once more functionality than the lazyloading flag
are suppported the test must be extended. */
++ld_state.ndsofiles;
}
}
return 0;
}
int
ld_handle_filename_list (struct filename_list *fnames)
{
struct filename_list *runp;
int res = 0;
for (runp = fnames; runp != NULL; runp = runp->next)
{
struct usedfiles *curp;
/* Create a record for the new file. */
curp = runp->real = ld_new_inputfile (runp->name, relocatable_file_type);
/* Set flags for group handling. */
curp->group_start = runp->group_start;
curp->group_end = runp->group_end;
/* Set as-needed flag from the file, not the command line. */
curp->as_needed = runp->as_needed;
/* Read the file and everything else which comes up, including
handling groups. */
do
res |= FILE_PROCESS (-1, curp, &ld_state, &curp);
while (curp != NULL);
}
/* Free the list. */
while (fnames != NULL)
{
runp = fnames;
fnames = fnames->next;
free (runp);
}
return res;
}
/* Handle opening of the given file with ELF descriptor. */
static int
open_elf (struct usedfiles *fileinfo, Elf *elf)
{
int res = 0;
if (elf == NULL)
error (EXIT_FAILURE, 0,
gettext ("cannot get descriptor for ELF file (%s:%d): %s\n"),
__FILE__, __LINE__, elf_errmsg (-1));
if (unlikely (elf_kind (elf) == ELF_K_NONE))
{
struct filename_list *fnames;
/* We don't have to look at this file again. */
fileinfo->status = closed;
/* Let's see whether this is a linker script. */
if (fileinfo->fd != -1)
/* Create a stream from the file handle we know. */
ldin = fdopen (fileinfo->fd, "r");
else
{
/* Get the memory for the archive member. */
char *content;
size_t contentsize;
/* Get the content of the file. */
content = elf_rawfile (elf, &contentsize);
if (content == NULL)
{
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
return 1;
}
/* The content of the file is available in memory. Read the
memory region as a stream. */
ldin = fmemopen (content, contentsize, "r");
}
/* No need for locking. */
__fsetlocking (ldin, FSETLOCKING_BYCALLER);
if (ldin == NULL)
error (EXIT_FAILURE, errno, gettext ("cannot open '%s'"),
fileinfo->rfname);
/* Parse the file. If it is a linker script no problems will be
reported. */
ld_state.srcfiles = NULL;
ldlineno = 1;
ld_scan_version_script = 0;
ldin_fname = fileinfo->rfname;
res = ldparse ();
fclose (ldin);
if (fileinfo->fd != -1 && !fileinfo->fd_passed)
{
/* We won't need the file descriptor again. */
close (fileinfo->fd);
fileinfo->fd = -1;
}
elf_end (elf);
if (unlikely (res != 0))
/* Something went wrong during parsing. */
return 1;
/* This is no ELF file. */
fileinfo->elf = NULL;
/* Now we have to handle eventual INPUT and GROUP statements in
the script. Read the files mentioned. */
fnames = ld_state.srcfiles;
if (fnames != NULL)
{
struct filename_list *oldp;
/* Convert the list into a normal single-linked list. */
oldp = fnames;
fnames = fnames->next;
oldp->next = NULL;
/* Remove the list from the state structure. */
ld_state.srcfiles = NULL;
if (unlikely (ld_handle_filename_list (fnames) != 0))
return 1;
}
return 0;
}
/* Store the file info. */
fileinfo->elf = elf;
/* The file is ready for action. */
fileinfo->status = opened;
return 0;
}
static int
add_whole_archive (struct usedfiles *fileinfo)
{
Elf *arelf;
Elf_Cmd cmd = ELF_C_READ_MMAP_PRIVATE;
int res = 0;
while ((arelf = elf_begin (fileinfo->fd, cmd, fileinfo->elf)) != NULL)
{
Elf_Arhdr *arhdr = elf_getarhdr (arelf);
struct usedfiles *newp;
if (arhdr == NULL)
abort ();
/* Just to be sure; since these are no files in the archive
these names should never be returned. */
assert (strcmp (arhdr->ar_name, "/") != 0);
assert (strcmp (arhdr->ar_name, "//") != 0);
newp = ld_new_inputfile (arhdr->ar_name, relocatable_file_type);
newp->archive_file = fileinfo;
if (unlikely (ld_state.trace_files))
print_file_name (stdout, newp, 1, 1);
/* This shows that this file is contained in an archive. */
newp->fd = -1;
/* Store the ELF descriptor. */
newp->elf = arelf;
/* Show that we are open for business. */
newp->status = opened;
/* Proces the file, add all the symbols etc. */
res = file_process2 (newp);
if (unlikely (res != 0))
break;
/* Advance to the next archive element. */
cmd = elf_next (arelf);
}
return res;
}
static int
extract_from_archive (struct usedfiles *fileinfo)
{
static int archive_seq;
int res = 0;
if (fileinfo->archive_seq == 0)
/* This is an archive we are not using completely. Give it a
unique number. */
fileinfo->archive_seq = ++archive_seq;
/* If there are no unresolved symbols don't do anything. */
assert (ld_state.extract_rule == defaultextract
|| ld_state.extract_rule == weakextract);
if ((likely (ld_state.extract_rule == defaultextract)
? ld_state.nunresolved_nonweak : ld_state.nunresolved) == 0)
return 0;
Elf_Arsym *syms;
size_t nsyms;
/* Get all the symbols. */
syms = elf_getarsym (fileinfo->elf, &nsyms);
if (syms == NULL)
{
cannot_read_archive:
error (0, 0, gettext ("cannot read archive `%s': %s"),
fileinfo->rfname, elf_errmsg (-1));
/* We cannot use this archive anymore. */
fileinfo->status = closed;
return 1;
}
/* Now add all the symbols to the hash table. Note that there
can potentially be duplicate definitions. We'll always use
the first definition. */
// XXX Is this a compatible behavior?
bool any_used;
do
{
any_used = false;
size_t cnt;
for (cnt = 0; cnt < nsyms; ++cnt)
{
struct symbol search = { .name = syms[cnt].as_name };
struct symbol *sym = ld_symbol_tab_find (&ld_state.symbol_tab,
syms[cnt].as_hash, &search);
if (sym != NULL && ! sym->defined)
{
/* The symbol is referenced and not defined. */
Elf *arelf;
Elf_Arhdr *arhdr;
struct usedfiles *newp;
/* Find the archive member for this symbol. */
if (unlikely (elf_rand (fileinfo->elf, syms[cnt].as_off)
!= syms[cnt].as_off))
goto cannot_read_archive;
/* Note: no test of a failing 'elf_begin' call. That's fine
since 'elf'getarhdr' will report the problem. */
arelf = elf_begin (fileinfo->fd, ELF_C_READ_MMAP_PRIVATE,
fileinfo->elf);
arhdr = elf_getarhdr (arelf);
if (arhdr == NULL)
goto cannot_read_archive;
/* We have all the information and an ELF handle for the
archive member. Create the normal data structure for
a file now. */
newp = ld_new_inputfile (obstack_strdup (&ld_state.smem,
arhdr->ar_name),
relocatable_file_type);
newp->archive_file = fileinfo;
if (unlikely (ld_state.trace_files))
print_file_name (stdout, newp, 1, 1);
/* This shows that this file is contained in an archive. */
newp->fd = -1;
/* Store the ELF descriptor. */
newp->elf = arelf;
/* Show that we are open for business. */
newp->status = in_archive;
/* Now read the file and add all the symbols. */
res = file_process2 (newp);
if (unlikely (res != 0))
return res;
any_used = true;
}
}
if (any_used)
{
/* This is an archive therefore it must have a number. */
assert (fileinfo->archive_seq != 0);
ld_state.last_archive_used = fileinfo->archive_seq;
}
}
while (any_used);
return res;
}
static int
file_process2 (struct usedfiles *fileinfo)
{
int res;
if (likely (elf_kind (fileinfo->elf) == ELF_K_ELF))
{
/* The first time we get here we read the ELF header. */
#if NATIVE_ELF != 0
if (likely (fileinfo->ehdr == NULL))
#else
if (likely (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_NONE))
#endif
{
XElf_Ehdr *ehdr;
#if NATIVE_ELF != 0
ehdr = xelf_getehdr (fileinfo->elf, fileinfo->ehdr);
#else
xelf_getehdr_copy (fileinfo->elf, ehdr, fileinfo->ehdr);
#endif
if (ehdr == NULL)
{
fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
fileinfo->rfname, __FILE__, __LINE__);
fileinfo->status = closed;
return 1;
}
if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL
&& unlikely (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_DYN))
/* XXX Add ebl* function to query types which are allowed
to link in. */
{
char buf[64];
print_file_name (stderr, fileinfo, 1, 0);
fprintf (stderr,
gettext ("file of type %s cannot be linked in\n"),
ebl_object_type_name (ld_state.ebl,
FILEINFO_EHDR (fileinfo->ehdr).e_type,
buf, sizeof (buf)));
fileinfo->status = closed;
return 1;
}
/* Make sure the file type matches the backend. */
if (FILEINFO_EHDR (fileinfo->ehdr).e_machine
!= ebl_get_elfmachine (ld_state.ebl))
{
fprintf (stderr, gettext ("\
%s: input file incompatible with ELF machine type %s\n"),
fileinfo->rfname,
ebl_backend_name (ld_state.ebl));
fileinfo->status = closed;
return 1;
}
/* Determine the section header string table section index. */
if (unlikely (elf_getshstrndx (fileinfo->elf, &fileinfo->shstrndx)
< 0))
{
fprintf (stderr, gettext ("\
%s: cannot get section header string table index: %s\n"),
fileinfo->rfname, elf_errmsg (-1));
fileinfo->status = closed;
return 1;
}
}
/* Now handle the different types of files. */
if (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_REL)
{
/* Add all the symbol. Relocatable files have symbol
tables. */
res = add_relocatable_file (fileinfo, SHT_SYMTAB);
}
else
{
bool has_l_name = fileinfo->file_type == archive_file_type;
assert (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN);
/* If the file is a DT_NEEDED dependency then the type is
already correctly specified. */
if (fileinfo->file_type != dso_needed_file_type)
fileinfo->file_type = dso_file_type;
/* We cannot use DSOs when generating relocatable objects. */
if (ld_state.file_type == relocatable_file_type)
{
error (0, 0, gettext ("\
cannot use DSO '%s' when generating relocatable object file"),
fileinfo->fname);
return 1;
}
/* Add all the symbols. For DSOs we are looking at the
dynamic symbol table. */
res = add_relocatable_file (fileinfo, SHT_DYNSYM);
/* We always have to have a dynamic section. */
assert (fileinfo->dynscn != NULL);
/* We have to remember the dependencies for this object. It
is necessary to look them up. */
XElf_Shdr_vardef (dynshdr);
xelf_getshdr (fileinfo->dynscn, dynshdr);
Elf_Data *dyndata = elf_getdata (fileinfo->dynscn, NULL);
/* XXX Should we flag the failure to get the dynamic section? */
if (dynshdr != NULL)
{
int cnt = dynshdr->sh_size / dynshdr->sh_entsize;
XElf_Dyn_vardef (dyn);
while (--cnt >= 0)
{
xelf_getdyn (dyndata, cnt, dyn);
if (dyn != NULL)
{
if(dyn->d_tag == DT_NEEDED)
{
struct usedfiles *newp;
newp = ld_new_inputfile (elf_strptr (fileinfo->elf,
dynshdr->sh_link,
dyn->d_un.d_val),
dso_needed_file_type);
/* Enqueue the newly found dependencies. */
// XXX Check that there not already a file with the
// same name.
CSNGL_LIST_ADD_REAR (ld_state.needed, newp);
}
else if (dyn->d_tag == DT_SONAME)
{
/* We use the DT_SONAME (this is what's there
for). */
fileinfo->soname = elf_strptr (fileinfo->elf,
dynshdr->sh_link,
dyn->d_un.d_val);
has_l_name = false;
}
}
}
}
/* Construct the file name if the DSO has no SONAME and the
file name comes from a -lXX parameter on the comment
line. */
if (unlikely (has_l_name))
{
/* The FNAME is the parameter the user specified on the
command line. We prepend "lib" and append ".so". */
size_t len = strlen (fileinfo->fname) + 7;
char *newp;
newp = (char *) obstack_alloc (&ld_state.smem, len);
strcpy (stpcpy (stpcpy (newp, "lib"), fileinfo->fname), ".so");
fileinfo->soname = newp;
}
}
}
else if (likely (elf_kind (fileinfo->elf) == ELF_K_AR))
{
if (unlikely (ld_state.extract_rule == allextract))
/* Which this option enabled we have to add all the object
files in the archive. */
res = add_whole_archive (fileinfo);
else if (ld_state.file_type == relocatable_file_type)
{
/* When generating a relocatable object we don't find files
in archives. */
if (verbose)
error (0, 0, gettext ("input file '%s' ignored"), fileinfo->fname);
res = 0;
}
else
{
if (ld_state.group_start_requested
&& ld_state.group_start_archive == NULL)
ld_state.group_start_archive = fileinfo;
if (ld_state.archives == NULL)
ld_state.archives = fileinfo;
if (ld_state.tailarchives != NULL)
ld_state.tailarchives->next = fileinfo;
ld_state.tailarchives = fileinfo;
/* Extract only the members from the archive which are
currently referenced by unresolved symbols. */
res = extract_from_archive (fileinfo);
}
}
else
/* This should never happen, we know about no other types. */
abort ();
return res;
}
/* Process a given file. The first parameter is a file descriptor for
the file which can be -1 to indicate the file has not yet been
found. The second parameter describes the file to be opened, the
last one is the state of the linker which among other information
contain the paths we look at. */
static int
ld_generic_file_process (int fd, struct usedfiles *fileinfo,
struct ld_state *statep, struct usedfiles **nextp)
{
int res = 0;
/* By default we go to the next file in the list. */
*nextp = fileinfo->next;
/* Set the flag to signal we are looking for a group start. */
if (unlikely (fileinfo->group_start))
{
ld_state.group_start_requested = true;
fileinfo->group_start = false;
}
/* If the file isn't open yet, open it now. */
if (likely (fileinfo->status == not_opened))
{
bool fd_passed = true;
if (likely (fd == -1))
{
/* Find the file ourselves. */
int err = open_along_path (fileinfo);
if (unlikely (err != 0))
/* We allow libraries and DSOs to be named more than once.
Don't report an error to the caller. */
return err == EAGAIN ? 0 : err;
fd_passed = false;
}
else
fileinfo->fd = fd;
/* Remember where we got the descriptor from. */
fileinfo->fd_passed = fd_passed;
/* We found the file. Now test whether it is a file type we can
handle.
XXX Do we need to have the ability to start from a given
position in the search path again to look for another file if
the one found has not the right type? */
res = open_elf (fileinfo, elf_begin (fileinfo->fd,
is_dso_p (fileinfo->fd)
? ELF_C_READ_MMAP
: ELF_C_READ_MMAP_PRIVATE, NULL));
if (unlikely (res != 0))
return res;
}
/* Now that we have opened the file start processing it. */
if (likely (fileinfo->status != closed))
res = file_process2 (fileinfo);
/* Determine which file to look at next. */
if (unlikely (fileinfo->group_backref != NULL))
{
/* We only go back if an archive other than the one we would go
back to has been used in the last round. */
if (ld_state.last_archive_used > fileinfo->group_backref->archive_seq)
{
*nextp = fileinfo->group_backref;
ld_state.last_archive_used = 0;
}
else
{
/* If we come here this means that the archives we read so
far are not needed anymore. We can free some of the data
now. */
struct usedfiles *runp = ld_state.archives;
do
{
/* We don't need the ELF descriptor anymore. Unless there
are no files from the archive used this will not free
the whole file but only some data structures. */
elf_end (runp->elf);
runp->elf = NULL;
runp = runp->next;
}
while (runp != fileinfo->next);
/* Do not do this again. */
ld_state.archives = NULL;
/* Do not move on to the next archive. */
*nextp = fileinfo->next = NULL;
}
}
else if (unlikely (fileinfo->group_end))
{
/* This is the end of a group. We possibly have to go back.
Determine which file we would go back to and see whether it
makes sense. If there has not been an archive we don't have
to do anything. */
if (ld_state.group_start_requested)
{
if (ld_state.group_start_archive != ld_state.tailarchives)
/* The loop includes more than one archive, add the pointer. */
{
*nextp = ld_state.tailarchives->group_backref =
ld_state.group_start_archive;
ld_state.last_archive_used = 0;
}
else
/* We might still have to go back to the beginning of the
group if since the last archive other files have been
added. But we go back exactly once. */
if (ld_state.tailarchives != fileinfo)
{
*nextp = ld_state.group_start_archive;
ld_state.last_archive_used = 0;
}
}
/* Clear the flags. */
ld_state.group_start_requested = false;
ld_state.group_start_archive = NULL;
fileinfo->group_end = false;
}
return res;
}
/* Library names passed to the linker as -lXX represent files named
libXX.YY. The YY part can have different forms, depending on the
platform. The generic set is .so and .a (in this order). */
static const char **
ld_generic_lib_extensions (struct ld_state *statep __attribute__ ((__unused__)))
{
static const char *exts[] =
{
".so", ".a", NULL
};
return exts;
}
/* Flag unresolved symbols. */
static int
ld_generic_flag_unresolved (struct ld_state *statep)
{
int retval = 0;
if (ld_state.nunresolved_nonweak > 0)
{
/* Go through the list and determine the unresolved symbols. */
struct symbol *first;
struct symbol *s;
s = first = ld_state.unresolved->next;
do
{
if (! s->defined && ! s->weak)
{
/* Two special symbol we recognize: the symbol for the
GOT and the dynamic section. */
if (strcmp (s->name, "_GLOBAL_OFFSET_TABLE_") == 0
|| strcmp (s->name, "_DYNAMIC") == 0)
{
/* We will have to fill in more information later. */
ld_state.need_got = true;
/* Remember that we found it. */
if (s->name[1] == 'G')
ld_state.got_symbol = s;
else
ld_state.dyn_symbol = s;
}
else if (ld_state.file_type != dso_file_type || !ld_state.nodefs)
{
/* XXX The error message should get better. It should use
the debugging information if present to tell where in the
sources the undefined reference is. */
error (0, 0, gettext ("undefined symbol `%s' in %s"),
s->name, s->file->fname);
retval = 1;
}
}
/* We cannot decide here what to do with undefined
references which will come from DSO since we do not know
what kind of symbol we expect. Only when looking at the
relocations we can see whether we need a PLT entry or
only a GOT entry. */
s = s->next;
}
while (s != first);
}
return retval;
}
/* Close the given file. */
static int
ld_generic_file_close (struct usedfiles *fileinfo, struct ld_state *statep)
{
/* Close the ELF descriptor. */
elf_end (fileinfo->elf);
/* If we have opened the file descriptor close it. But we might
have done this already in which case FD is -1. */
if (!fileinfo->fd_passed && fileinfo->fd != -1)
close (fileinfo->fd);
/* We allocated the resolved file name. */
if (fileinfo->fname != fileinfo->rfname)
free ((char *) fileinfo->rfname);
return 0;
}
static void
new_generated_scn (enum scn_kind kind, const char *name, int type, int flags,
int entsize, int align)
{
struct scnhead *newp;
newp = (struct scnhead *) obstack_calloc (&ld_state.smem,
sizeof (struct scnhead));
newp->kind = kind;
newp->name = name;
newp->nameent = ebl_strtabadd (ld_state.shstrtab, name, 0);
newp->type = type;
newp->flags = flags;
newp->entsize = entsize;
newp->align = align;
newp->grp_signature = NULL;
newp->used = true;
/* All is well. Create now the data for the section and insert it
into the section table. */
ld_section_tab_insert (&ld_state.section_tab, elf_hash (name), newp);
}
/* Create the sections which are generated by the linker and are not
present in the input file. */
static void
ld_generic_generate_sections (struct ld_state *statep)
{
/* The relocation section type. */
int rel_type = REL_TYPE (&ld_state) == DT_REL ? SHT_REL : SHT_RELA;
/* When requested, every output file will have a build ID section. */
if (statep->build_id != NULL)
new_generated_scn (scn_dot_note_gnu_build_id, ".note.gnu.build-id",
SHT_NOTE, SHF_ALLOC, 0, 4);
/* When building dynamically linked object we have to include a
section containing a string describing the interpreter. This
should be at the very beginning of the file together with the
other information the ELF loader (kernel or wherever) has to look
at. We put it as the first section in the file.
We also have to create the dynamic segment which is a special
section the dynamic linker locates through an entry in the
program header. */
if (dynamically_linked_p ())
{
/* Use any versioning (defined or required)? */
bool use_versioning = false;
/* Use version requirements? */
bool need_version = false;
/* First the .interp section. */
if (ld_state.interp != NULL || ld_state.file_type != dso_file_type)
new_generated_scn (scn_dot_interp, ".interp", SHT_PROGBITS, SHF_ALLOC,
0, 1);
/* Now the .dynamic section. */
new_generated_scn (scn_dot_dynamic, ".dynamic", SHT_DYNAMIC,
DYNAMIC_SECTION_FLAGS (&ld_state),
xelf_fsize (ld_state.outelf, ELF_T_DYN, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* We will need in any case the dynamic symbol table (even in
the unlikely case that no symbol is exported or referenced
from a DSO). */
ld_state.need_dynsym = true;
new_generated_scn (scn_dot_dynsym, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
xelf_fsize (ld_state.outelf, ELF_T_SYM, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* It comes with a string table. */
new_generated_scn (scn_dot_dynstr, ".dynstr", SHT_STRTAB, SHF_ALLOC,
0, 1);
/* And a hashing table. */
// XXX For Linux/Alpha we need other sizes unless they change...
if (GENERATE_SYSV_HASH)
new_generated_scn (scn_dot_hash, ".hash", SHT_HASH, SHF_ALLOC,
sizeof (Elf32_Word), sizeof (Elf32_Word));
if (GENERATE_GNU_HASH)
new_generated_scn (scn_dot_gnu_hash, ".gnu.hash", SHT_GNU_HASH,
SHF_ALLOC, sizeof (Elf32_Word),
sizeof (Elf32_Word));
/* Create the section associated with the PLT if necessary. */
if (ld_state.nplt > 0)
{
/* Create the .plt section. */
/* XXX We might need a function which returns the section flags. */
new_generated_scn (scn_dot_plt, ".plt", SHT_PROGBITS,
SHF_ALLOC | SHF_EXECINSTR,
/* XXX Is the size correct? */
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* Create the relocation section for the .plt. This is always
separate even if the other relocation sections are combined. */
new_generated_scn (scn_dot_pltrel, ".rel.plt", rel_type, SHF_ALLOC,
rel_type == SHT_REL
? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
: xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* XXX We might need a function which returns the section flags. */
new_generated_scn (scn_dot_gotplt, ".got.plt", SHT_PROGBITS,
SHF_ALLOC | SHF_WRITE,
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* Mark all used DSOs as used. Determine whether any referenced
object uses symbol versioning. */
if (ld_state.from_dso != NULL)
{
struct symbol *srunp = ld_state.from_dso;
do
{
srunp->file->used = true;
if (srunp->file->verdefdata != NULL)
{
XElf_Versym versym;
/* The input DSO uses versioning. */
use_versioning = true;
/* We reference versions. */
need_version = true;
if (xelf_getversym_copy (srunp->file->versymdata,
srunp->symidx, versym) == NULL)
assert (! "xelf_getversym failed");
/* We cannot link explicitly with an older
version of a symbol. */
assert ((versym & 0x8000) == 0);
/* We cannot reference local (index 0) or plain
global (index 1) versions. */
assert (versym > 1);
/* Check whether we have already seen the
version and if not add it to the referenced
versions in the output file. */
if (! srunp->file->verdefused[versym])
{
srunp->file->verdefused[versym] = 1;
if (++srunp->file->nverdefused == 1)
/* Count the file if it is using versioning. */
++ld_state.nverdeffile;
++ld_state.nverdefused;
}
}
}
while ((srunp = srunp->next) != ld_state.from_dso);
}
/* Create the sections used to record version dependencies. */
if (need_version)
new_generated_scn (scn_dot_version_r, ".gnu.version_r",
SHT_GNU_verneed, SHF_ALLOC, 0,
xelf_fsize (ld_state.outelf, ELF_T_WORD, 1));
}
/* Now count the used DSOs since this is what the user
wants. */
int ndt_needed = 0;
if (ld_state.ndsofiles > 0)
{
struct usedfiles *frunp = ld_state.dsofiles;
do
if (! frunp->as_needed || frunp->used)
{
++ndt_needed;
if (frunp->lazyload)
/* We have to create another dynamic section
entry for the DT_POSFLAG_1 entry.
XXX Once more functionality than the lazyloading
flag are suppported the test must be
extended. */
++ndt_needed;
}
while ((frunp = frunp->next) != ld_state.dsofiles);
}
if (use_versioning)
new_generated_scn (scn_dot_version, ".gnu.version", SHT_GNU_versym,
SHF_ALLOC,
xelf_fsize (ld_state.outelf, ELF_T_HALF, 1),
xelf_fsize (ld_state.outelf, ELF_T_HALF, 1));
/* We need some entries all the time. */
ld_state.ndynamic = (7 + (ld_state.runpath != NULL
|| ld_state.rpath != NULL)
+ ndt_needed
+ (ld_state.init_symbol != NULL ? 1 : 0)
+ (ld_state.fini_symbol != NULL ? 1 : 0)
+ (use_versioning ? 1 : 0)
+ (need_version ? 2 : 0)
+ (ld_state.nplt > 0 ? 4 : 0)
+ (ld_state.relsize_total > 0 ? 3 : 0));
}
/* When creating a relocatable file or when we are not stripping the
output file we create a symbol table. */
ld_state.need_symtab = (ld_state.file_type == relocatable_file_type
|| ld_state.strip == strip_none);
/* Add the .got section if needed. */
if (ld_state.need_got)
/* XXX We might need a function which returns the section flags. */
new_generated_scn (scn_dot_got, ".got", SHT_PROGBITS,
SHF_ALLOC | SHF_WRITE,
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
/* Add the .rel.dyn section. */
if (ld_state.relsize_total > 0)
new_generated_scn (scn_dot_dynrel, ".rel.dyn", rel_type, SHF_ALLOC,
rel_type == SHT_REL
? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
: xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
}
/* Callback function registered with on_exit to make sure the temporary
files gets removed if something goes wrong. */
static void
remove_tempfile (int status, void *arg)
{
if (status != 0 && ld_state.tempfname != NULL)
unlink (ld_state.tempfname);
}
/* Create the output file. The file name is given or "a.out". We
create as much of the ELF structure as possible. */
static int
ld_generic_open_outfile (struct ld_state *statep, int machine, int klass,
int data)
{
/* We do not create the new file right away with the final name.
This would destroy an existing file with this name before a
replacement is finalized. We create instead a temporary file in
the same directory. */
if (ld_state.outfname == NULL)
ld_state.outfname = "a.out";
size_t outfname_len = strlen (ld_state.outfname);
char *tempfname = (char *) obstack_alloc (&ld_state.smem,
outfname_len + sizeof (".XXXXXX"));
ld_state.tempfname = tempfname;
int fd;
int try = 0;
while (1)
{
strcpy (mempcpy (tempfname, ld_state.outfname, outfname_len), ".XXXXXX");
/* The use of mktemp() here is fine. We do not want to use
mkstemp() since then the umask isn't used. And the output
file will have these permissions anyhow. Any intruder could
change the file later if it would be possible now. */
if (mktemp (tempfname) != NULL
&& (fd = open (tempfname, O_RDWR | O_EXCL | O_CREAT | O_NOFOLLOW,
ld_state.file_type == relocatable_file_type
? DEFFILEMODE : ACCESSPERMS)) != -1)
break;
/* Failed this round. We keep trying a number of times. */
if (++try >= 10)
error (EXIT_FAILURE, errno, gettext ("cannot create output file"));
}
ld_state.outfd = fd;
/* Make sure we remove the temporary file in case something goes
wrong. */
on_exit (remove_tempfile, NULL);
/* Create the ELF file data for the output file. */
Elf *elf = ld_state.outelf = elf_begin (fd,
conserve_memory
? ELF_C_WRITE : ELF_C_WRITE_MMAP,
NULL);
if (elf == NULL)
error (EXIT_FAILURE, 0,
gettext ("cannot create ELF descriptor for output file: %s"),
elf_errmsg (-1));
/* Create the basic data structures. */
if (! xelf_newehdr (elf, klass))
/* Couldn't create the ELF header. Very bad. */
error (EXIT_FAILURE, 0,
gettext ("could not create ELF header for output file: %s"),
elf_errmsg (-1));
/* And get the current header so that we can modify it. */
XElf_Ehdr_vardef (ehdr);
xelf_getehdr (elf, ehdr);
assert (ehdr != NULL);
/* Set the machine type. */
ehdr->e_machine = machine;
/* Modify it according to the info we have here and now. */
if (ld_state.file_type == executable_file_type)