/* Copyright (C) 2001-2011 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. This file 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; either version 3 of the License, or (at your option) any later version. 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 this program. If not, see <http://www.gnu.org/licenses/>. */ #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; if (list == NULL) return 0; 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_getshdrnum (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_getshdrnum (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_getshdrnum (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_getshdrstrndx (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) ehdr->e_type = ET_EXEC; else if (ld_state.file_type == dso_file_type) ehdr->e_type = ET_DYN; else { assert (ld_state.file_type == relocatable_file_type); ehdr->e_type = ET_REL; } /* Set the ELF version. */ ehdr->e_version = EV_CURRENT; /* Set the endianness. */ ehdr->e_ident[EI_DATA] = data; /* Write the ELF header information back. */ (void) xelf_update_ehdr (elf, ehdr); return 0; } /* We compute the offsets of the various copied objects and the total size of the memory needed. */ // XXX The method used here is simple: go from front to back and pack // the objects in this order. A more space efficient way would // actually trying to pack the objects as dense as possible. But this // is more expensive. static void compute_copy_reloc_offset (XElf_Shdr *shdr) { struct symbol *runp = ld_state.from_dso; assert (runp != NULL); XElf_Off maxalign = 1; XElf_Off offset = 0; do if (runp->need_copy) { /* Determine alignment for the symbol. */ // XXX The question is how? The symbol record itself does not // have the information. So we have to be conservative and // assume the alignment of the section the symbol is in. // XXX We can be more precise. Use the offset from the beginning // of the section and determine the largest power of two with // module zero. XElf_Off symalign = MAX (SCNINFO_SHDR (runp->file->scninfo[runp->scndx].shdr).sh_addralign, 1); /* Keep track of the maximum alignment requirement. */ maxalign = MAX (maxalign, symalign); /* Align current position. */ offset = (offset + symalign - 1) & ~(symalign - 1); runp->merge.value = offset; offset += runp->size; } while ((runp = runp->next) != ld_state.from_dso); shdr->sh_type = SHT_NOBITS; shdr->sh_size = offset; shdr->sh_addralign = maxalign; } static void compute_common_symbol_offset (XElf_Shdr *shdr) { struct symbol *runp = ld_state.common_syms; assert (runp != NULL); XElf_Off maxalign = 1; XElf_Off offset = 0; do { /* Determine alignment for the symbol. */ XElf_Off symalign = runp->merge.value; /* Keep track of the maximum alignment requirement. */ maxalign = MAX (maxalign, symalign); /* Align current position. */ offset = (offset + symalign - 1) & ~(symalign - 1); runp->merge.value = offset; offset += runp->size; } while ((runp = runp->next) != ld_state.common_syms); shdr->sh_type = SHT_NOBITS; shdr->sh_size = offset; shdr->sh_addralign = maxalign; } static void sort_sections_generic (void) { /* XXX TBI */ abort (); } static int match_section (const char *osectname, struct filemask_section_name *sectmask, struct scnhead **scnhead, bool new_section, size_t segment_nr) { struct scninfo *prevp; struct scninfo *runp; struct scninfo *notused; if (fnmatch (sectmask->section_name->name, (*scnhead)->name, 0) != 0) /* The section name does not match. */ return new_section; /* If this is a section generated by the linker it doesn't contain the regular information (i.e., input section data etc) and must be handle special. */ if ((*scnhead)->kind != scn_normal) { (*scnhead)->name = osectname; (*scnhead)->segment_nr = segment_nr; /* We have to count note section since they get their own program header entry. */ if ((*scnhead)->type == SHT_NOTE) ++ld_state.nnotesections; ld_state.allsections[ld_state.nallsections++] = (*scnhead); return true; } /* Now we have to match the file names of the input files. Some of the sections here might not match. */ runp = (*scnhead)->last->next; prevp = (*scnhead)->last; notused = NULL; do { /* Base of the file name the section comes from. */ const char *brfname = basename (runp->fileinfo->rfname); /* If the section isn't used, the name doesn't match the positive inclusion list, or the name does match the negative inclusion list, ignore the section. */ if (!runp->used || (sectmask->filemask != NULL && fnmatch (sectmask->filemask, brfname, 0) != 0) || (sectmask->excludemask != NULL && fnmatch (sectmask->excludemask, brfname, 0) == 0)) { /* This file does not match the file name masks. */ if (notused == NULL) notused = runp; prevp = runp; runp = runp->next; if (runp == notused) runp = NULL; } /* The section fulfills all requirements, add it to the output file with the correct section name etc. */ else { struct scninfo *found = runp; /* Remove this input section data buffer from the list. */ if (prevp != runp) runp = prevp->next = runp->next; else { free (*scnhead); *scnhead = NULL; runp = NULL; } /* Create a new section for the output file if the 'new_section' flag says so. Otherwise append the buffer to the last section which we created in one of the last calls. */ if (new_section) { struct scnhead *newp; newp = (struct scnhead *) obstack_calloc (&ld_state.smem, sizeof (*newp)); newp->kind = scn_normal; newp->name = osectname; newp->type = SCNINFO_SHDR (found->shdr).sh_type; /* Executable or DSO do not have section groups. Drop that information. */ newp->flags = SCNINFO_SHDR (found->shdr).sh_flags & ~SHF_GROUP; newp->segment_nr = segment_nr; newp->last = found->next = found; newp->used = true; newp->relsize = found->relsize; newp->entsize = SCNINFO_SHDR (found->shdr).sh_entsize; /* We have to count note section since they get their own program header entry. */ if (newp->type == SHT_NOTE) ++ld_state.nnotesections; ld_state.allsections[ld_state.nallsections++] = newp; new_section = false; } else { struct scnhead *queued; queued = ld_state.allsections[ld_state.nallsections - 1]; found->next = queued->last->next; queued->last = queued->last->next = found; /* If the linker script forces us to add incompatible sections together do so. But reflect this in the type and flags of the resulting file. */ if (queued->type != SCNINFO_SHDR (found->shdr).sh_type) /* XXX Any better choice? */ queued->type = SHT_PROGBITS; if (queued->flags != SCNINFO_SHDR (found->shdr).sh_flags) /* Executable or DSO do not have section groups. Drop that information. */ queued->flags = ebl_sh_flags_combine (ld_state.ebl, queued->flags, SCNINFO_SHDR (found->shdr).sh_flags & ~SHF_GROUP); /* Accumulate the relocation section size. */ queued->relsize += found->relsize; } } } while (runp != NULL); return new_section; } static void sort_sections_lscript (void) { struct scnhead *temp[ld_state.nallsections]; /* Make a copy of the section head pointer array. */ memcpy (temp, ld_state.allsections, ld_state.nallsections * sizeof (temp[0])); size_t nallsections = ld_state.nallsections; /* Convert the output segment list in a single-linked list. */ struct output_segment *segment = ld_state.output_segments->next; ld_state.output_segments->next = NULL; ld_state.output_segments = segment; /* Put the sections in the correct order in the array in the state structure. This might involve merging of sections and also renaming the containing section in the output file. */ ld_state.nallsections = 0; size_t segment_nr; size_t last_writable = ~0ul; for (segment_nr = 0; segment != NULL; segment = segment->next, ++segment_nr) { struct output_rule *orule; for (orule = segment->output_rules; orule != NULL; orule = orule->next) if (orule->tag == output_section) { struct input_rule *irule; bool new_section = true; for (irule = orule->val.section.input; irule != NULL; irule = irule->next) if (irule->tag == input_section) { size_t cnt; for (cnt = 0; cnt < nallsections; ++cnt) if (temp[cnt] != NULL) new_section = match_section (orule->val.section.name, irule->val.section, &temp[cnt], new_section, segment_nr); } } if ((segment->mode & PF_W) != 0) last_writable = ld_state.nallsections - 1; } /* In case we have to create copy relocations or we have common symbols, find the last writable segment and add one more data block. It will be a NOBITS block and take up no disk space. This is why it is important to get the last block. */ if (ld_state.ncopy > 0 || ld_state.common_syms != NULL) { if (last_writable == ~0ul) error (EXIT_FAILURE, 0, "no writable segment"); if (ld_state.allsections[last_writable]->type != SHT_NOBITS) { /* Make room in the ALLSECTIONS array for a new section. There is guaranteed room in the array. We add the new entry after the last writable section. */ ++last_writable; memmove (&ld_state.allsections[last_writable + 1], &ld_state.allsections[last_writable], (ld_state.nallsections - last_writable) * sizeof (ld_state.allsections[0])); ld_state.allsections[last_writable] = (struct scnhead *) obstack_calloc (&ld_state.smem, sizeof (struct scnhead)); /* Name for the new section. */ ld_state.allsections[last_writable]->name = ".bss"; /* Type: NOBITS. */ ld_state.allsections[last_writable]->type = SHT_NOBITS; /* Same segment as the last writable section. */ ld_state.allsections[last_writable]->segment_nr = ld_state.allsections[last_writable - 1]->segment_nr; } } /* Create common symbol data block. */ if (ld_state.ncopy > 0) { #if NATIVE_ELF struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr)); si->shdr = (XElf_Shdr *) (si + 1); #else struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem, sizeof (*si)); #endif /* Get the information regarding the symbols with copy relocations. */ compute_copy_reloc_offset (&SCNINFO_SHDR (si->shdr)); /* This section is needed. */ si->used = true; /* Remember for later the section data structure. */ ld_state.copy_section = si; if (likely (ld_state.allsections[last_writable]->last != NULL)) { si->next = ld_state.allsections[last_writable]->last->next; ld_state.allsections[last_writable]->last->next = si; ld_state.allsections[last_writable]->last = si; } else ld_state.allsections[last_writable]->last = si->next = si; } /* Create common symbol data block. */ if (ld_state.common_syms != NULL) { #if NATIVE_ELF struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr)); si->shdr = (XElf_Shdr *) (si + 1); #else struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem, sizeof (*si)); #endif /* Get the information regarding the symbols with copy relocations. */ compute_common_symbol_offset (&SCNINFO_SHDR (si->shdr)); /* This section is needed. */ si->used = true; /* Remember for later the section data structure. */ ld_state.common_section = si; if (likely (ld_state.allsections[last_writable]->last != NULL)) { si->next = ld_state.allsections[last_writable]->last->next; ld_state.allsections[last_writable]->last->next = si; ld_state.allsections[last_writable]->last = si; } else ld_state.allsections[last_writable]->last = si->next = si; } } /* Create the output sections now. This requires knowledge about all the sections we will need. It may be necessary to sort sections in the order they are supposed to appear in the executable. The sorting use many different kinds of information to optimize the resulting binary. Important is to respect segment boundaries and the needed alignment. The mode of the segments will be determined afterwards automatically by the output routines. The generic sorting routines work in one of two possible ways: - if a linker script specifies the sections to be used in the output and assigns them to a segment this information is used; - otherwise the linker will order the sections based on permissions and some special knowledge about section names.*/ static void ld_generic_create_sections (struct ld_state *statep) { struct scngroup *groups; size_t cnt; /* For relocatable object we don't have to bother sorting the sections and we do want to preserve the relocation sections as they appear in the input files. */ if (ld_state.file_type != relocatable_file_type) { /* Collect all the relocation sections. They are handled separately. */ struct scninfo *list = NULL; for (cnt = 0; cnt < ld_state.nallsections; ++cnt) if ((ld_state.allsections[cnt]->type == SHT_REL || ld_state.allsections[cnt]->type == SHT_RELA) /* The generated relocation sections are not of any interest here. */ && ld_state.allsections[cnt]->last != NULL) { if (list == NULL) list = ld_state.allsections[cnt]->last; else { /* Merge the sections list. */ struct scninfo *first = list->next; list->next = ld_state.allsections[cnt]->last->next; ld_state.allsections[cnt]->last->next = first; list = ld_state.allsections[cnt]->last; } /* Remove the entry from the section list. */ ld_state.allsections[cnt] = NULL; } ld_state.rellist = list; if (ld_state.output_segments == NULL) /* Sort using builtin rules. */ sort_sections_generic (); else sort_sections_lscript (); } /* Now iterate over the input sections and create the sections in the order they are required in the output file. */ for (cnt = 0; cnt < ld_state.nallsections; ++cnt) { struct scnhead *head = ld_state.allsections[cnt]; Elf_Scn *scn; XElf_Shdr_vardef (shdr); /* Don't handle unused sections. */ if (!head->used) continue; /* We first have to create the section group if necessary. Section group sections must come (in section index order) before any of the section contained. This all is necessary only for relocatable object as other object types are not allowed to contain section groups. */ if (ld_state.file_type == relocatable_file_type && unlikely (head->flags & SHF_GROUP)) { /* There is at least one section which is contained in a section group in the input file. This means we must create a section group here as well. The only problem is that not all input files have to have to same kind of partitioning of the sections. I.e., sections A and B in one input file and sections B and C in another input file can be in one group. That will result in a group containing the sections A, B, and C in the output file. */ struct scninfo *runp; Elf32_Word here_groupidx = 0; struct scngroup *here_group; struct member *newp; /* First check whether any section is already in a group. In this case we have to add this output section, too. */ runp = head->last; do { assert (runp->grpid != 0); here_groupidx = runp->fileinfo->scninfo[runp->grpid].outscnndx; if (here_groupidx != 0) break; } while ((runp = runp->next) != head->last); if (here_groupidx == 0) { /* We need a new section group section. */ scn = elf_newscn (ld_state.outelf); xelf_getshdr (scn, shdr); if (shdr == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); here_group = (struct scngroup *) xmalloc (sizeof (*here_group)); here_group->outscnidx = here_groupidx = elf_ndxscn (scn); here_group->nscns = 0; here_group->member = NULL; here_group->next = ld_state.groups; /* Pick a name for the section. To keep it meaningful we use a name used in the input files. If the section group in the output file should contain section which were in section groups of different names in the input files this is the users problem. */ here_group->nameent = ebl_strtabadd (ld_state.shstrtab, elf_strptr (runp->fileinfo->elf, runp->fileinfo->shstrndx, SCNINFO_SHDR (runp->shdr).sh_name), 0); /* Signature symbol. */ here_group->symbol = runp->fileinfo->scninfo[runp->grpid].symbols; ld_state.groups = here_group; } else { /* Search for the group with this index. */ here_group = ld_state.groups; while (here_group->outscnidx != here_groupidx) here_group = here_group->next; } /* Add the new output section. */ newp = (struct member *) alloca (sizeof (*newp)); newp->scn = head; #ifndef NDT_NEEDED newp->next = NULL; #endif CSNGL_LIST_ADD_REAR (here_group->member, newp); ++here_group->nscns; /* Store the section group index in all input files. */ runp = head->last; do { assert (runp->grpid != 0); if (runp->fileinfo->scninfo[runp->grpid].outscnndx == 0) runp->fileinfo->scninfo[runp->grpid].outscnndx = here_groupidx; else assert (runp->fileinfo->scninfo[runp->grpid].outscnndx == here_groupidx); } while ((runp = runp->next) != head->last); } /* We'll use this section so get it's name in the section header string table. */ if (head->kind == scn_normal) head->nameent = ebl_strtabadd (ld_state.shstrtab, head->name, 0); /* Create a new section in the output file and add all data from all the sections we read. */ scn = elf_newscn (ld_state.outelf); head->scnidx = elf_ndxscn (scn); xelf_getshdr (scn, shdr); if (shdr == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); assert (head->type != SHT_NULL); assert (head->type != SHT_SYMTAB); assert (head->type != SHT_DYNSYM || head->kind != scn_normal); assert (head->type != SHT_STRTAB || head->kind != scn_normal); assert (head->type != SHT_GROUP); shdr->sh_type = head->type; shdr->sh_flags = head->flags; shdr->sh_addralign = head->align; shdr->sh_entsize = head->entsize; assert (shdr->sh_entsize != 0 || (shdr->sh_flags & SHF_MERGE) == 0); (void) xelf_update_shdr (scn, shdr); /* We have to know the section index of the dynamic symbol table right away. */ if (head->kind == scn_dot_dynsym) ld_state.dynsymscnidx = elf_ndxscn (scn); } /* Actually create the section group sections. */ groups = ld_state.groups; while (groups != NULL) { Elf_Scn *scn; Elf_Data *data; Elf32_Word *grpdata; struct member *runp; scn = elf_getscn (ld_state.outelf, groups->outscnidx); assert (scn != NULL); data = elf_newdata (scn); if (data == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); data->d_size = (groups->nscns + 1) * sizeof (Elf32_Word); data->d_buf = grpdata = (Elf32_Word *) xmalloc (data->d_size); data->d_type = ELF_T_WORD; data->d_version = EV_CURRENT; data->d_off = 0; /* XXX What better to use? */ data->d_align = sizeof (Elf32_Word); /* The first word in the section is the flag word. */ /* XXX Set COMDATA flag is necessary. */ grpdata[0] = 0; runp = groups->member->next; cnt = 1; do /* Fill in the index of the section. */ grpdata[cnt++] = runp->scn->scnidx; while ((runp = runp->next) != groups->member->next); groups = groups->next; } } static bool reduce_symbol_p (XElf_Sym *sym, struct Ebl_Strent *strent) { const char *str; const char *version; struct id_list search; struct id_list *verp; bool result = ld_state.default_bind_local; if (XELF_ST_BIND (sym->st_info) == STB_LOCAL || sym->st_shndx == SHN_UNDEF) /* We don't have to do anything to local symbols here. */ /* XXX Any section value in [SHN_LORESERVER,SHN_XINDEX) need special treatment? */ return false; /* XXX Handle other symbol bindings. */ assert (XELF_ST_BIND (sym->st_info) == STB_GLOBAL || XELF_ST_BIND (sym->st_info) == STB_WEAK); str = ebl_string (strent); version = strchr (str, VER_CHR); if (version != NULL) { search.id = strndupa (str, version - str); if (*++version == VER_CHR) /* Skip the second '@' signaling a default definition. */ ++version; } else { search.id = str; version = ""; } verp = ld_version_str_tab_find (&ld_state.version_str_tab, elf_hash (search.id), &search); while (verp != NULL) { /* We have this symbol in the version hash table. Now match the version name. */ if (strcmp (verp->u.s.versionname, version) == 0) /* Match! */ return verp->u.s.local; verp = verp->next; } /* XXX Add test for wildcard version symbols. */ return result; } static XElf_Addr eval_expression (struct expression *expr, XElf_Addr addr) { XElf_Addr val = ~((XElf_Addr) 0); switch (expr->tag) { case exp_num: val = expr->val.num; break; case exp_sizeof_headers: { /* The 'elf_update' call determine the offset of the first section. The the size of the header. */ XElf_Shdr_vardef (shdr); xelf_getshdr (elf_getscn (ld_state.outelf, 1), shdr); assert (shdr != NULL); val = shdr->sh_offset; } break; case exp_pagesize: val = ld_state.pagesize; break; case exp_id: /* We are here computing only address expressions. It seems not to be necessary to handle any variable but ".". Let's avoid the complication. If it turns up to be needed we can add it. */ if (strcmp (expr->val.str, ".") != 0) error (EXIT_FAILURE, 0, gettext ("\ address computation expression contains variable '%s'"), expr->val.str); val = addr; break; case exp_mult: val = (eval_expression (expr->val.binary.left, addr) * eval_expression (expr->val.binary.right, addr)); break; case exp_div: val = (eval_expression (expr->val.binary.left, addr) / eval_expression (expr->val.binary.right, addr)); break; case exp_mod: val = (eval_expression (expr->val.binary.left, addr) % eval_expression (expr->val.binary.right, addr)); break; case exp_plus: val = (eval_expression (expr->val.binary.left, addr) + eval_expression (expr->val.binary.right, addr)); break; case exp_minus: val = (eval_expression (expr->val.binary.left, addr) - eval_expression (expr->val.binary.right, addr)); break; case exp_and: val = (eval_expression (expr->val.binary.left, addr) & eval_expression (expr->val.binary.right, addr)); break; case exp_or: val = (eval_expression (expr->val.binary.left, addr) | eval_expression (expr->val.binary.right, addr)); break; case exp_align: val = eval_expression (expr->val.child, addr); if ((val & (val - 1)) != 0) error (EXIT_FAILURE, 0, gettext ("argument '%" PRIuMAX "' of ALIGN in address computation expression is no power of two"), (uintmax_t) val); val = (addr + val - 1) & ~(val - 1); break; } return val; } /* Find a good as possible size for the hash table so that all the non-zero entries in HASHCODES don't collide too much and the table isn't too large. There is no exact formular for this so we use a heuristic. Depending on the optimization level the search is longer or shorter. */ static size_t optimal_bucket_size (Elf32_Word *hashcodes, size_t maxcnt, int optlevel) { size_t minsize; size_t maxsize; size_t bestsize; uint64_t bestcost; size_t size; uint32_t *counts; uint32_t *lengths; if (maxcnt == 0) return 0; /* When we are not optimizing we run only very few tests. */ if (optlevel <= 0) { minsize = maxcnt; maxsize = maxcnt + 10000 / maxcnt; } else { /* Does not make much sense to start with a smaller table than one which has at least four collisions. */ minsize = MAX (1, maxcnt / 4); /* We look for a best fit in the range of up to eigth times the number of elements. */ maxsize = 2 * maxcnt + (6 * MIN (optlevel, 100) * maxcnt) / 100; } bestsize = maxcnt; bestcost = UINT_MAX; /* Array for counting the collisions and chain lengths. */ counts = (uint32_t *) xmalloc ((maxcnt + 1 + maxsize) * sizeof (uint32_t)); lengths = &counts[maxcnt + 1]; for (size = minsize; size <= maxsize; ++size) { size_t inner; uint64_t cost; uint32_t maxlength; uint64_t success; uint32_t acc; double factor; memset (lengths, '\0', size * sizeof (uint32_t)); memset (counts, '\0', (maxcnt + 1) * sizeof (uint32_t)); /* Determine how often each hash bucket is used. */ assert (hashcodes[0] == 0); for (inner = 1; inner < maxcnt; ++inner) ++lengths[hashcodes[inner] % size]; /* Determine the lengths. */ maxlength = 0; for (inner = 0; inner < size; ++inner) { ++counts[lengths[inner]]; if (lengths[inner] > maxlength) maxlength = lengths[inner]; } /* Determine successful lookup length. */ acc = 0; success = 0; for (inner = 0; inner <= maxlength; ++inner) { acc += inner; success += counts[inner] * acc; } /* We can compute two factors now: the average length of a positive search and the average length of a negative search. We count the number of comparisons which have to look at the names themselves. Recognizing that the chain ended is not accounted for since it's almost for free. Which lookup is more important depends on the kind of DSO. If it is a system DSO like libc it is expected that most lookups succeed. Otherwise most lookups fail. */ if (ld_state.is_system_library) factor = (1.0 * (double) success / (double) maxcnt + 0.3 * (double) maxcnt / (double) size); else factor = (0.3 * (double) success / (double) maxcnt + 1.0 * (double) maxcnt / (double) size); /* Combine the lookup cost factor. The 1/16th addend adds penalties for too large table sizes. */ cost = (2 + maxcnt + size) * (factor + 1.0 / 16.0); #if 0 printf ("maxcnt = %d, size = %d, cost = %Ld, success = %g, fail = %g, factor = %g\n", maxcnt, size, cost, (double) success / (double) maxcnt, (double) maxcnt / (double) size, factor); #endif /* Compare with current best results. */ if (cost < bestcost) { bestcost = cost; bestsize = size; } } free (counts); return bestsize; } static void optimal_gnu_hash_size (Elf32_Word *hashcodes, size_t maxcnt, int optlevel, size_t *bitmask_nwords, size_t *shift, size_t *nbuckets) { // XXX Implement something real *bitmask_nwords = 256; *shift = 6; *nbuckets = 3 * maxcnt / 2; } static XElf_Addr find_entry_point (void) { XElf_Addr result; if (ld_state.entry != NULL) { struct symbol search = { .name = ld_state.entry }; struct symbol *syment; syment = ld_symbol_tab_find (&ld_state.symbol_tab, elf_hash (ld_state.entry), &search); if (syment != NULL && syment->defined) { /* We found the symbol. */ Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf, ld_state.symscnidx), NULL); XElf_Sym_vardef (sym); sym = NULL; if (data != NULL) xelf_getsym (data, ld_state.dblindirect[syment->outsymidx], sym); if (sym == NULL && ld_state.need_dynsym && syment->outdynsymidx != 0) { /* Use the dynamic symbol table if available. */ data = elf_getdata (elf_getscn (ld_state.outelf, ld_state.dynsymscnidx), NULL); sym = NULL; if (data != NULL) xelf_getsym (data, syment->outdynsymidx, sym); } if (sym != NULL) return sym->st_value; /* XXX What to do if the output has no non-dynamic symbol table and the dynamic symbol table does not contain the symbol? */ assert (ld_state.need_symtab); assert (ld_state.symscnidx != 0); } } /* We couldn't find the symbol or none was given. Use the first address of the ".text" section then. */ result = 0; /* In DSOs this is no fatal error. They usually have no entry points. In this case we set the entry point to zero, which makes sure it will always fail. */ if (ld_state.file_type == executable_file_type) { if (ld_state.entry != NULL) error (0, 0, gettext ("\ cannot find entry symbol '%s': defaulting to %#0*" PRIx64), ld_state.entry, xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18, (uint64_t) result); else error (0, 0, gettext ("\ no entry symbol specified: defaulting to %#0*" PRIx64), xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18, (uint64_t) result); } return result; } static void fillin_special_symbol (struct symbol *symst, size_t scnidx, size_t nsym, Elf_Data *symdata, struct Ebl_Strtab *strtab) { assert (ld_state.file_type != relocatable_file_type); XElf_Sym_vardef (sym); xelf_getsym_ptr (symdata, nsym, sym); /* The name offset will be filled in later. */ sym->st_name = 0; /* Traditionally: globally visible. */ sym->st_info = XELF_ST_INFO (symst->local ? STB_LOCAL : STB_GLOBAL, symst->type); sym->st_other = symst->hidden ? STV_HIDDEN : STV_DEFAULT; /* Reference to the GOT or dynamic section. Since the GOT and dynamic section are only created for executables and DSOs it cannot be that the section index is too large. */ assert (scnidx != 0); assert (scnidx < SHN_LORESERVE || scnidx == SHN_ABS); sym->st_shndx = scnidx; /* We want the beginning of the section. */ sym->st_value = 0; // XXX What size? sym->st_size = 0; /* Determine the size of the section. */ if (scnidx != SHN_ABS) { Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf, scnidx), NULL); assert (data != NULL); sym->st_size = data->d_size; /* Make sure there is no second data block. */ assert (elf_getdata (elf_getscn (ld_state.outelf, scnidx), data) == NULL); } /* Insert symbol into the symbol table. Note that we do not have to use xelf_update_symshdx. */ (void) xelf_update_sym (symdata, nsym, sym); /* Cross-references. */ ndxtosym[nsym] = symst; symst->outsymidx = nsym; /* Add the name to the string table. */ symstrent[nsym] = ebl_strtabadd (strtab, symst->name, 0); } static void new_dynamic_entry (Elf_Data *data, int idx, XElf_Sxword tag, XElf_Addr val) { XElf_Dyn_vardef (dyn); xelf_getdyn_ptr (data, idx, dyn); dyn->d_tag = tag; dyn->d_un.d_ptr = val; (void) xelf_update_dyn (data, idx, dyn); } static void allocate_version_names (struct usedfiles *runp, struct Ebl_Strtab *dynstrtab) { /* If this DSO has no versions skip it. */ if (runp->status != opened || runp->verdefdata == NULL) return; /* Add the object name. */ int offset = 0; while (1) { XElf_Verdef_vardef (def); XElf_Verdaux_vardef (aux); /* Get data at the next offset. */ xelf_getverdef (runp->verdefdata, offset, def); assert (def != NULL); xelf_getverdaux (runp->verdefdata, offset + def->vd_aux, aux); assert (aux != NULL); assert (def->vd_ndx <= runp->nverdef); if (def->vd_ndx == 1 || runp->verdefused[def->vd_ndx] != 0) { runp->verdefent[def->vd_ndx] = ebl_strtabadd (dynstrtab, elf_strptr (runp->elf, runp->dynsymstridx, aux->vda_name), 0); if (def->vd_ndx > 1) runp->verdefused[def->vd_ndx] = ld_state.nextveridx++; } if (def->vd_next == 0) /* That were all versions. */ break; offset += def->vd_next; } } static XElf_Off create_verneed_data (XElf_Off offset, Elf_Data *verneeddata, struct usedfiles *runp, int *ntotal) { size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1); size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1); int need_offset; bool filled = false; GElf_Verneed verneed; GElf_Vernaux vernaux; int ndef = 0; size_t cnt; /* If this DSO has no versions skip it. */ if (runp->nverdefused == 0) return offset; /* We fill in the Verneed record last. Remember the offset. */ need_offset = offset; offset += verneed_size; for (cnt = 2; cnt <= runp->nverdef; ++cnt) if (runp->verdefused[cnt] != 0) { assert (runp->verdefent[cnt] != NULL); if (filled) { vernaux.vna_next = vernaux_size; (void) gelf_update_vernaux (verneeddata, offset, &vernaux); offset += vernaux_size; } vernaux.vna_hash = elf_hash (ebl_string (runp->verdefent[cnt])); vernaux.vna_flags = 0; vernaux.vna_other = runp->verdefused[cnt]; vernaux.vna_name = ebl_strtaboffset (runp->verdefent[cnt]); filled = true; ++ndef; } assert (filled); vernaux.vna_next = 0; (void) gelf_update_vernaux (verneeddata, offset, &vernaux); offset += vernaux_size; verneed.vn_version = VER_NEED_CURRENT; verneed.vn_cnt = ndef; verneed.vn_file = ebl_strtaboffset (runp->verdefent[1]); /* The first auxiliary entry is always found directly after the verneed entry. */ verneed.vn_aux = verneed_size; verneed.vn_next = --*ntotal > 0 ? offset - need_offset : 0; (void) gelf_update_verneed (verneeddata, need_offset, &verneed); return offset; } /* Callback for qsort to sort dynamic string table. */ static Elf32_Word *global_hashcodes; static size_t global_nbuckets; static int sortfct_hashval (const void *p1, const void *p2) { size_t idx1 = *(size_t *) p1; size_t idx2 = *(size_t *) p2; int def1 = ndxtosym[idx1]->defined && !ndxtosym[idx1]->in_dso; int def2 = ndxtosym[idx2]->defined && !ndxtosym[idx2]->in_dso; if (! def1 && def2) return -1; if (def1 && !def2) return 1; if (! def1) return 0; Elf32_Word hval1 = (global_hashcodes[ndxtosym[idx1]->outdynsymidx] % global_nbuckets); Elf32_Word hval2 = (global_hashcodes[ndxtosym[idx2]->outdynsymidx] % global_nbuckets); if (hval1 < hval2) return -1; if (hval1 > hval2) return 1; return 0; } /* Sort the dynamic symbol table. The GNU hash table lookup assumes that all symbols with the same hash value module the bucket table size follow one another. This avoids the extra hash chain table. There is no need (and no way) to perform this operation if we do not use the new hash table format. */ static void create_gnu_hash (size_t nsym_local, size_t nsym, size_t nsym_dyn, Elf32_Word *gnuhashcodes) { size_t gnu_bitmask_nwords = 0; size_t gnu_shift = 0; size_t gnu_nbuckets = 0; Elf32_Word *gnu_bitmask = NULL; Elf32_Word *gnu_buckets = NULL; Elf32_Word *gnu_chain = NULL; XElf_Shdr_vardef (shdr); /* Determine the "optimal" bucket size. */ optimal_gnu_hash_size (gnuhashcodes, nsym_dyn, ld_state.optlevel, &gnu_bitmask_nwords, &gnu_shift, &gnu_nbuckets); /* Create the .gnu.hash section data structures. */ Elf_Scn *hashscn = elf_getscn (ld_state.outelf, ld_state.gnuhashscnidx); xelf_getshdr (hashscn, shdr); Elf_Data *hashdata = elf_newdata (hashscn); if (shdr == NULL || hashdata == NULL) error (EXIT_FAILURE, 0, gettext ("\ cannot create GNU hash table section for output file: %s"), elf_errmsg (-1)); shdr->sh_link = ld_state.dynsymscnidx; (void) xelf_update_shdr (hashscn, shdr); hashdata->d_size = (xelf_fsize (ld_state.outelf, ELF_T_ADDR, gnu_bitmask_nwords) + (4 + gnu_nbuckets + nsym_dyn) * sizeof (Elf32_Word)); hashdata->d_buf = xcalloc (1, hashdata->d_size); hashdata->d_align = sizeof (Elf32_Word); hashdata->d_type = ELF_T_WORD; hashdata->d_off = 0; ((Elf32_Word *) hashdata->d_buf)[0] = gnu_nbuckets; ((Elf32_Word *) hashdata->d_buf)[2] = gnu_bitmask_nwords; ((Elf32_Word *) hashdata->d_buf)[3] = gnu_shift; gnu_bitmask = &((Elf32_Word *) hashdata->d_buf)[4]; gnu_buckets = &gnu_bitmask[xelf_fsize (ld_state.outelf, ELF_T_ADDR, gnu_bitmask_nwords) / sizeof (*gnu_buckets)]; gnu_chain = &gnu_buckets[gnu_nbuckets]; #ifndef NDEBUG void *endp = &gnu_chain[nsym_dyn]; #endif assert (endp == (void *) ((char *) hashdata->d_buf + hashdata->d_size)); size_t *remap = xmalloc (nsym_dyn * sizeof (size_t)); #ifndef NDEBUG size_t nsym_dyn_cnt = 1; #endif for (size_t cnt = nsym_local; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) { assert (ndxtosym[cnt]->outdynsymidx > 0); assert (ndxtosym[cnt]->outdynsymidx < nsym_dyn); remap[ndxtosym[cnt]->outdynsymidx] = cnt; #ifndef NDEBUG ++nsym_dyn_cnt; #endif } assert (nsym_dyn_cnt == nsym_dyn); // XXX Until we can rely on qsort_r use global variables. global_hashcodes = gnuhashcodes; global_nbuckets = gnu_nbuckets; qsort (remap + 1, nsym_dyn - 1, sizeof (size_t), sortfct_hashval); bool bm32 = (xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1) == sizeof (Elf32_Word)); size_t first_defined = 0; Elf64_Word bitmask_idxbits = gnu_bitmask_nwords - 1; Elf32_Word last_bucket = 0; for (size_t cnt = 1; cnt < nsym_dyn; ++cnt) { if (first_defined == 0) { if (! ndxtosym[remap[cnt]]->defined || ndxtosym[remap[cnt]]->in_dso) goto next; ((Elf32_Word *) hashdata->d_buf)[1] = first_defined = cnt; } Elf32_Word hval = gnuhashcodes[ndxtosym[remap[cnt]]->outdynsymidx]; if (bm32) { Elf32_Word *bsw = &gnu_bitmask[(hval / 32) & bitmask_idxbits]; assert ((void *) gnu_bitmask <= (void *) bsw); assert ((void *) bsw < (void *) gnu_buckets); *bsw |= 1 << (hval & 31); *bsw |= 1 << ((hval >> gnu_shift) & 31); } else { Elf64_Word *bsw = &((Elf64_Word *) gnu_bitmask)[(hval / 64) & bitmask_idxbits]; assert ((void *) gnu_bitmask <= (void *) bsw); assert ((void *) bsw < (void *) gnu_buckets); *bsw |= 1 << (hval & 63); *bsw |= 1 << ((hval >> gnu_shift) & 63); } size_t this_bucket = hval % gnu_nbuckets; if (cnt == first_defined || this_bucket != last_bucket) { if (cnt != first_defined) { /* Terminate the previous chain. */ assert ((void *) &gnu_chain[cnt - first_defined - 1] < endp); gnu_chain[cnt - first_defined - 1] |= 1; } assert (this_bucket < gnu_nbuckets); gnu_buckets[this_bucket] = cnt; last_bucket = this_bucket; } assert (cnt >= first_defined); assert (cnt - first_defined < nsym_dyn); gnu_chain[cnt - first_defined] = hval & ~1u; next: ndxtosym[remap[cnt]]->outdynsymidx = cnt; } /* Terminate the last chain. */ if (first_defined != 0) { assert (nsym_dyn > first_defined); assert (nsym_dyn - first_defined - 1 < nsym_dyn); gnu_chain[nsym_dyn - first_defined - 1] |= 1; hashdata->d_size -= first_defined * sizeof (Elf32_Word); } else /* We do not need any hash table. */ // XXX do { } while (0); free (remap); } /* Create the SysV-style hash table. */ static void create_hash (size_t nsym_local, size_t nsym, size_t nsym_dyn, Elf32_Word *hashcodes) { size_t nbucket = 0; Elf32_Word *bucket = NULL; Elf32_Word *chain = NULL; XElf_Shdr_vardef (shdr); /* Determine the "optimal" bucket size. If we also generate the new-style hash function there is no need to waste effort and space on the old one which should not be used. Make it as small as possible. */ if (GENERATE_GNU_HASH) nbucket = 1; else nbucket = optimal_bucket_size (hashcodes, nsym_dyn, ld_state.optlevel); /* Create the .hash section data structures. */ Elf_Scn *hashscn = elf_getscn (ld_state.outelf, ld_state.hashscnidx); xelf_getshdr (hashscn, shdr); Elf_Data *hashdata = elf_newdata (hashscn); if (shdr == NULL || hashdata == NULL) error (EXIT_FAILURE, 0, gettext ("\ cannot create hash table section for output file: %s"), elf_errmsg (-1)); shdr->sh_link = ld_state.dynsymscnidx; (void) xelf_update_shdr (hashscn, shdr); hashdata->d_size = (2 + nsym_dyn + nbucket) * sizeof (Elf32_Word); hashdata->d_buf = xcalloc (1, hashdata->d_size); hashdata->d_align = sizeof (Elf32_Word); hashdata->d_type = ELF_T_WORD; hashdata->d_off = 0; ((Elf32_Word *) hashdata->d_buf)[0] = nbucket; ((Elf32_Word *) hashdata->d_buf)[1] = nsym_dyn; bucket = &((Elf32_Word *) hashdata->d_buf)[2]; chain = &((Elf32_Word *) hashdata->d_buf)[2 + nbucket]; for (size_t cnt = nsym_local; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) { size_t dynidx = ndxtosym[cnt]->outdynsymidx; size_t hashidx = hashcodes[dynidx] % nbucket; if (bucket[hashidx] == 0) bucket[hashidx] = dynidx; else { hashidx = bucket[hashidx]; while (chain[hashidx] != 0) hashidx = chain[hashidx]; chain[hashidx] = dynidx; } } } static void create_build_id_section (Elf_Scn *scn) { /* We know how large the section will be so we can create it now. */ Elf_Data *d = elf_newdata (scn); if (d == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create build ID section: %s"), elf_errmsg (-1)); d->d_type = ELF_T_BYTE; d->d_version = EV_CURRENT; /* The note section header. */ assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); d->d_size = sizeof (GElf_Nhdr); /* The string is four bytes long. */ d->d_size += sizeof (ELF_NOTE_GNU); assert (d->d_size % 4 == 0); if (strcmp (ld_state.build_id, "md5") == 0 || strcmp (ld_state.build_id, "uuid") == 0) d->d_size += 16; else if (strcmp (ld_state.build_id, "sha1") == 0) d->d_size += 20; else { assert (ld_state.build_id[0] == '0' && ld_state.build_id[1] == 'x'); /* Use an upper limit of the possible number of bytes generated from the string. */ d->d_size += strlen (ld_state.build_id) / 2; } d->d_buf = xcalloc (d->d_size, 1); d->d_off = 0; d->d_align = 0; } static void compute_hash_sum (void (*hashfct) (const void *, size_t, void *), void *ctx) { /* The call cannot fail. */ size_t shstrndx; (void) elf_getshdrstrndx (ld_state.outelf, &shstrndx); const char *ident = elf_getident (ld_state.outelf, NULL); bool same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB && __BYTE_ORDER == __LITTLE_ENDIAN) || (ident[EI_DATA] == ELFDATA2MSB && __BYTE_ORDER == __BIG_ENDIAN)); /* Iterate over all sections to find those which are not strippable. */ Elf_Scn *scn = NULL; while ((scn = elf_nextscn (ld_state.outelf, scn)) != NULL) { /* Get the section header. */ GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); assert (shdr != NULL); if (SECTION_STRIP_P (shdr, elf_strptr (ld_state.outelf, shstrndx, shdr->sh_name), true)) /* The section can be stripped. Don't use it. */ continue; /* Do not look at NOBITS sections. */ if (shdr->sh_type == SHT_NOBITS) continue; /* Iterate through the list of data blocks. */ Elf_Data *data = NULL; while ((data = INTUSE(elf_getdata) (scn, data)) != NULL) /* If the file byte order is the same as the host byte order process the buffer directly. If the data is just a stream of bytes which the library will not convert we can use it as well. */ if (likely (same_byte_order) || data->d_type == ELF_T_BYTE) hashfct (data->d_buf, data->d_size, ctx); else { /* Convert the data to file byte order. */ if (gelf_xlatetof (ld_state.outelf, data, data, ident[EI_DATA]) == NULL) error (EXIT_FAILURE, 0, gettext ("\ cannot convert section data to file format: %s"), elf_errmsg (-1)); hashfct (data->d_buf, data->d_size, ctx); /* And convert it back. */ if (gelf_xlatetom (ld_state.outelf, data, data, ident[EI_DATA]) == NULL) error (EXIT_FAILURE, 0, gettext ("\ cannot convert section data to memory format: %s"), elf_errmsg (-1)); } } } /* Iterate over the sections */ static void compute_build_id (void) { Elf_Data *d = elf_getdata (elf_getscn (ld_state.outelf, ld_state.buildidscnidx), NULL); assert (d != NULL); GElf_Nhdr *hdr = d->d_buf; hdr->n_namesz = sizeof (ELF_NOTE_GNU); hdr->n_type = NT_GNU_BUILD_ID; char *dp = mempcpy (hdr + 1, ELF_NOTE_GNU, sizeof (ELF_NOTE_GNU)); if (strcmp (ld_state.build_id, "sha1") == 0) { /* Compute the SHA1 sum of various parts of the generated file. We compute the hash sum over the external representation. */ struct sha1_ctx ctx; sha1_init_ctx (&ctx); /* Compute the hash sum by running over all sections. */ compute_hash_sum ((void (*) (const void *, size_t, void *)) sha1_process_bytes, &ctx); /* We are done computing the checksum. */ (void) sha1_finish_ctx (&ctx, dp); hdr->n_descsz = SHA1_DIGEST_SIZE; } else if (strcmp (ld_state.build_id, "md5") == 0) { /* Compute the MD5 sum of various parts of the generated file. We compute the hash sum over the external representation. */ struct md5_ctx ctx; md5_init_ctx (&ctx); /* Compute the hash sum by running over all sections. */ compute_hash_sum ((void (*) (const void *, size_t, void *)) md5_process_bytes, &ctx); /* We are done computing the checksum. */ (void) md5_finish_ctx (&ctx, dp); hdr->n_descsz = MD5_DIGEST_SIZE; } else if (strcmp (ld_state.build_id, "uuid") == 0) { int fd = open ("/dev/urandom", O_RDONLY); if (fd == -1) error (EXIT_FAILURE, errno, gettext ("cannot open '%s'"), "/dev/urandom"); if (TEMP_FAILURE_RETRY (read (fd, dp, 16)) != 16) error (EXIT_FAILURE, 0, gettext ("cannot read enough data for UUID")); close (fd); hdr->n_descsz = 16; } else { const char *cp = ld_state.build_id + 2; /* The form of the string has been verified before so here we can simplify the scanning. */ do { if (isxdigit (cp[0])) { char ch1 = tolower (cp[0]); char ch2 = tolower (cp[1]); *dp++ = (((isdigit (ch1) ? ch1 - '0' : ch1 - 'a' + 10) << 4) | (isdigit (ch2) ? ch2 - '0' : ch2 - 'a' + 10)); } else ++cp; } while (*cp != '\0'); } } /* Create the output file. For relocatable files what basically has to happen is that all sections from all input files are written into the output file. Sections with the same name are combined (offsets adjusted accordingly). The symbol tables are combined in one single table. When stripping certain symbol table entries are omitted. For executables (shared or not) we have to create the program header, additional sections like the .interp, eventually (in addition) create a dynamic symbol table and a dynamic section. Also the relocations have to be processed differently. */ static int ld_generic_create_outfile (struct ld_state *statep) { struct scnlist { size_t scnidx; struct scninfo *scninfo; struct scnlist *next; }; struct scnlist *rellist = NULL; size_t cnt; Elf_Scn *symscn = NULL; Elf_Scn *xndxscn = NULL; Elf_Scn *strscn = NULL; struct Ebl_Strtab *strtab = NULL; struct Ebl_Strtab *dynstrtab = NULL; XElf_Shdr_vardef (shdr); Elf_Data *data; Elf_Data *symdata = NULL; Elf_Data *xndxdata = NULL; struct usedfiles *file; size_t nsym; size_t nsym_local; size_t nsym_allocated; size_t nsym_dyn = 0; Elf32_Word *dblindirect = NULL; #ifndef NDEBUG bool need_xndx; #endif Elf_Scn *shstrtab_scn; size_t shstrtab_ndx; XElf_Ehdr_vardef (ehdr); struct Ebl_Strent *symtab_ent = NULL; struct Ebl_Strent *xndx_ent = NULL; struct Ebl_Strent *strtab_ent = NULL; struct Ebl_Strent *shstrtab_ent; struct scngroup *groups; Elf_Scn *dynsymscn = NULL; Elf_Data *dynsymdata = NULL; Elf_Data *dynstrdata = NULL; Elf32_Word *hashcodes = NULL; Elf32_Word *gnuhashcodes = NULL; size_t nsym_dyn_allocated = 0; Elf_Scn *versymscn = NULL; Elf_Data *versymdata = NULL; if (ld_state.need_symtab) { /* First create the symbol table. We need the symbol section itself and the string table for it. */ symscn = elf_newscn (ld_state.outelf); ld_state.symscnidx = elf_ndxscn (symscn); symdata = elf_newdata (symscn); if (symdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create symbol table for output file: %s"), elf_errmsg (-1)); symdata->d_type = ELF_T_SYM; /* This is an estimated size, but it will definitely cap the real value. We might have to adjust the number later. */ nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot + ld_state.nusedsections + ld_state.nlscript_syms); symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_allocated); /* Optionally the extended section table. */ /* XXX Is SHN_LORESERVE correct? Do we need some other sections? */ if (unlikely (ld_state.nusedsections >= SHN_LORESERVE)) { xndxscn = elf_newscn (ld_state.outelf); ld_state.xndxscnidx = elf_ndxscn (xndxscn); xndxdata = elf_newdata (xndxscn); if (xndxdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create symbol table for output file: %s"), elf_errmsg (-1)); /* The following relies on the fact that Elf32_Word and Elf64_Word have the same size. */ xndxdata->d_type = ELF_T_WORD; /* This is an estimated size, but it will definitely cap the real value. we might have to adjust the number later. */ xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD, nsym_allocated); /* The first entry is left empty, clear it here and now. */ xndxdata->d_buf = memset (xmalloc (xndxdata->d_size), '\0', xelf_fsize (ld_state.outelf, ELF_T_WORD, 1)); xndxdata->d_off = 0; /* XXX Should use an ebl function. */ xndxdata->d_align = sizeof (Elf32_Word); } } else { assert (ld_state.need_dynsym); /* First create the symbol table. We need the symbol section itself and the string table for it. */ symscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx); symdata = elf_newdata (symscn); if (symdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create symbol table for output file: %s"), elf_errmsg (-1)); symdata->d_version = EV_CURRENT; symdata->d_type = ELF_T_SYM; /* This is an estimated size, but it will definitely cap the real value. We might have to adjust the number later. */ nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot - ld_state.nlocalsymbols + ld_state.nlscript_syms); symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_allocated); } /* The first entry is left empty, clear it here and now. */ symdata->d_buf = memset (xmalloc (symdata->d_size), '\0', xelf_fsize (ld_state.outelf, ELF_T_SYM, 1)); symdata->d_off = 0; /* XXX This is ugly but how else can it be done. */ symdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); /* Allocate another array to keep track of the handles for the symbol names. */ symstrent = (struct Ebl_Strent **) xcalloc (nsym_allocated, sizeof (struct Ebl_Strent *)); /* By starting at 1 we effectively add a null entry. */ nsym = 1; /* Iteration over all sections. */ for (cnt = 0; cnt < ld_state.nallsections; ++cnt) { struct scnhead *head = ld_state.allsections[cnt]; Elf_Scn *scn; struct scninfo *runp; XElf_Off offset; Elf32_Word xndx; /* Don't handle unused sections at all. */ if (!head->used) continue; /* Get the section handle. */ scn = elf_getscn (ld_state.outelf, head->scnidx); if (unlikely (head->kind == scn_dot_interp)) { Elf_Data *outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* This is the string we'll put in the section. */ const char *interp = ld_state.interp ?: "/lib/ld.so.1"; /* Create the section data. */ outdata->d_buf = (void *) interp; outdata->d_size = strlen (interp) + 1; outdata->d_type = ELF_T_BYTE; outdata->d_off = 0; outdata->d_align = 1; outdata->d_version = EV_CURRENT; /* Remember the index of this section. */ ld_state.interpscnidx = head->scnidx; continue; } if (unlikely (head->kind == scn_dot_got)) { /* Remember the index of this section. */ ld_state.gotscnidx = elf_ndxscn (scn); /* Give the backend the change to initialize the section. */ INITIALIZE_GOT (&ld_state, scn); continue; } if (unlikely (head->kind == scn_dot_gotplt)) { /* Remember the index of this section. */ ld_state.gotpltscnidx = elf_ndxscn (scn); /* Give the backend the change to initialize the section. */ INITIALIZE_GOTPLT (&ld_state, scn); continue; } if (unlikely (head->kind == scn_dot_dynrel)) { Elf_Data *outdata; outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); outdata->d_size = ld_state.relsize_total; outdata->d_buf = xmalloc (outdata->d_size); outdata->d_type = (REL_TYPE (&ld_state) == DT_REL ? ELF_T_REL : ELF_T_RELA); outdata->d_off = 0; outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); /* Remember the index of this section. */ ld_state.reldynscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_dynamic)) { /* Only create the data for now. */ Elf_Data *outdata; /* Account for a few more entries we have to add. */ if (ld_state.dt_flags != 0) ++ld_state.ndynamic; if (ld_state.dt_flags_1 != 0) ++ld_state.ndynamic; if (ld_state.dt_feature_1 != 0) ++ld_state.ndynamic; outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* Create the section data. */ outdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_DYN, ld_state.ndynamic); outdata->d_buf = xcalloc (1, outdata->d_size); outdata->d_type = ELF_T_DYN; outdata->d_off = 0; outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); /* Remember the index of this section. */ ld_state.dynamicscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_dynsym)) { /* We already know the section index. */ assert (ld_state.dynsymscnidx == elf_ndxscn (scn)); continue; } if (unlikely (head->kind == scn_dot_dynstr)) { /* Remember the index of this section. */ ld_state.dynstrscnidx = elf_ndxscn (scn); /* Create the string table. */ dynstrtab = ebl_strtabinit (true); /* XXX TBI We have to add all the strings which are needed in the dynamic section here. This means DT_FILTER, DT_AUXILIARY, ... entries. */ if (ld_state.ndsofiles > 0) { struct usedfiles *frunp = ld_state.dsofiles; do if (! frunp->as_needed || frunp->used) frunp->sonameent = ebl_strtabadd (dynstrtab, frunp->soname, 0); while ((frunp = frunp->next) != ld_state.dsofiles); } /* Add the runtime path information. The strings are stored in the .dynstr section. If both rpath and runpath are defined the runpath information is used. */ if (ld_state.runpath != NULL || ld_state.rpath != NULL) { struct pathelement *startp; struct pathelement *prunp; int tag; size_t len; char *str; char *cp; if (ld_state.runpath != NULL) { startp = ld_state.runpath; tag = DT_RUNPATH; } else { startp = ld_state.rpath; tag = DT_RPATH; } /* Determine how long the string will be. */ for (len = 0, prunp = startp; prunp != NULL; prunp = prunp->next) len += strlen (prunp->pname) + 1; cp = str = (char *) obstack_alloc (&ld_state.smem, len); /* Copy the string. */ for (prunp = startp; prunp != NULL; prunp = prunp->next) { cp = stpcpy (cp, prunp->pname); *cp++ = ':'; } /* Remove the last colon. */ cp[-1] = '\0'; /* Remember the values until we can generate the dynamic section. */ ld_state.rxxpath_strent = ebl_strtabadd (dynstrtab, str, len); ld_state.rxxpath_tag = tag; } continue; } if (unlikely (head->kind == scn_dot_hash)) { /* Remember the index of this section. */ ld_state.hashscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_gnu_hash)) { /* Remember the index of this section. */ ld_state.gnuhashscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_plt)) { /* Remember the index of this section. */ ld_state.pltscnidx = elf_ndxscn (scn); /* Give the backend the change to initialize the section. */ INITIALIZE_PLT (&ld_state, scn); continue; } if (unlikely (head->kind == scn_dot_pltrel)) { /* Remember the index of this section. */ ld_state.pltrelscnidx = elf_ndxscn (scn); /* Give the backend the change to initialize the section. */ INITIALIZE_PLTREL (&ld_state, scn); continue; } if (unlikely (head->kind == scn_dot_version)) { /* Remember the index of this section. */ ld_state.versymscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_version_r)) { /* Remember the index of this section. */ ld_state.verneedscnidx = elf_ndxscn (scn); continue; } if (unlikely (head->kind == scn_dot_note_gnu_build_id)) { /* Remember the index of this section. */ ld_state.buildidscnidx = elf_ndxscn (scn); create_build_id_section (scn); continue; } /* If we come here we must be handling a normal section. */ assert (head->kind == scn_normal); /* Create an STT_SECTION entry in the symbol table. But not for the symbolic symbol table. */ if (ld_state.need_symtab) { /* XXX Can we be cleverer and do this only if needed? */ XElf_Sym_vardef (sym); /* Optimization ahead: in the native linker we get a pointer to the final location so that the following code writes directly in the correct place. Otherwise we write into the local variable first. */ xelf_getsym_ptr (symdata, nsym, sym); /* Usual section symbol: local, no specific information, except the section index. The offset here is zero, the start address will later be added. */ sym->st_name = 0; sym->st_info = XELF_ST_INFO (STB_LOCAL, STT_SECTION); sym->st_other = 0; sym->st_value = 0; sym->st_size = 0; /* In relocatable files the section index can be too big for the ElfXX_Sym struct. we have to deal with the extended symbol table. */ if (likely (head->scnidx < SHN_LORESERVE)) { sym->st_shndx = head->scnidx; xndx = 0; } else { sym->st_shndx = SHN_XINDEX; xndx = head->scnidx; } /* Commit the change. See the optimization above, this does not change the symbol table entry. But the extended section index table entry is always written, if there is such a table. */ assert (nsym < nsym_allocated); xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 0); /* Remember the symbol's index in the symbol table. */ head->scnsymidx = nsym++; } if (head->type == SHT_REL || head->type == SHT_RELA) { /* Remember that we have to fill in the symbol table section index. */ if (ld_state.file_type == relocatable_file_type) { struct scnlist *newp; newp = (struct scnlist *) alloca (sizeof (*newp)); newp->scnidx = head->scnidx; newp->scninfo = head->last->next; #ifndef NDEBUG newp->next = NULL; #endif SNGL_LIST_PUSH (rellist, newp); } else { /* When we create an executable or a DSO we don't simply copy the existing relocations. Instead many will be resolved, others will be converted. Create a data buffer large enough to contain the contents which we will fill in later. */ int type = head->type == SHT_REL ? ELF_T_REL : ELF_T_RELA; data = elf_newdata (scn); if (data == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); data->d_size = xelf_fsize (ld_state.outelf, type, head->relsize); data->d_buf = xcalloc (data->d_size, 1); data->d_type = type; data->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); data->d_off = 0; continue; } } /* Recognize string and merge flag and handle them. */ if (head->flags & SHF_MERGE) { /* We merge the contents of the sections. For this we do not look at the contents of section directly. Instead we look at the symbols of the section. */ Elf_Data *outdata; /* Concatenate the lists of symbols for all sections. XXX In case any input section has no symbols associated (this happens for debug sections) we cannot use this method. Implement parsing the other debug sections and find the string pointers. For now we don't merge. */ runp = head->last->next; if (runp->symbols == NULL) { head->flags &= ~SHF_MERGE; goto no_merge; } head->symbols = runp->symbols; while ((runp = runp->next) != head->last->next) { if (runp->symbols == NULL) { head->flags &= ~SHF_MERGE; head->symbols = NULL; goto no_merge; } struct symbol *oldhead = head->symbols->next_in_scn; head->symbols->next_in_scn = runp->symbols->next_in_scn; runp->symbols->next_in_scn = oldhead; head->symbols = runp->symbols; } /* Create the output section. */ outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* We use different merging algorithms for performance reasons. We can easily handle single-byte and wchar_t-wide character strings. All other cases (which really should happen in real life) are handled by the generic code. */ if (SCNINFO_SHDR (head->last->shdr).sh_entsize == 1 && (head->flags & SHF_STRINGS)) { /* Simple, single-byte string matching. */ struct Ebl_Strtab *mergestrtab; struct symbol *symrunp; Elf_Data *locsymdata = NULL; Elf_Data *locdata = NULL; mergestrtab = ebl_strtabinit (false); symrunp = head->symbols->next_in_scn; file = NULL; do { /* Accelarate the loop. We cache the file information since it might very well be the case that the previous entry was from the same file. */ if (symrunp->file != file) { /* Remember the file. */ file = symrunp->file; /* Symbol table data from that file. */ locsymdata = file->symtabdata; /* String section data. */ locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn, NULL); assert (locdata != NULL); /* While we are at it, remember the output section. If we don't access the string data section the section won't be in the output file. So it is sufficient to do the work here. */ file->scninfo[symrunp->scndx].outscnndx = head->scnidx; } /* Get the symbol information. This provides us the offset into the string data section. */ XElf_Sym_vardef (sym); xelf_getsym (locsymdata, symrunp->symidx, sym); assert (sym != NULL); /* Get the data from the file. Note that we access the raw section data; no endian-ness issues with single-byte strings. */ symrunp->merge.handle = ebl_strtabadd (mergestrtab, (char *) locdata->d_buf + sym->st_value, 0); } while ((symrunp = symrunp->next_in_scn) != head->symbols->next_in_scn); /* All strings have been added. Create the final table. */ ebl_strtabfinalize (mergestrtab, outdata); /* Compute the final offsets in the section. */ symrunp = runp->symbols; do { symrunp->merge.value = ebl_strtaboffset (symrunp->merge.handle); symrunp->merged = 1; } while ((symrunp = symrunp->next_in_scn) != runp->symbols); /* We don't need the string table anymore. */ ebl_strtabfree (mergestrtab); } else if (likely (SCNINFO_SHDR (head->last->shdr).sh_entsize == sizeof (wchar_t)) && likely (head->flags & SHF_STRINGS)) { /* Simple, wchar_t string merging. */ struct Ebl_WStrtab *mergestrtab; struct symbol *symrunp; Elf_Data *locsymdata = NULL; Elf_Data *locdata = NULL; mergestrtab = ebl_wstrtabinit (false); symrunp = runp->symbols; file = NULL; do { /* Accelarate the loop. We cache the file information since it might very well be the case that the previous entry was from the same file. */ if (symrunp->file != file) { /* Remember the file. */ file = symrunp->file; /* Symbol table data from that file. */ locsymdata = file->symtabdata; /* String section data. */ locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn, NULL); assert (locdata != NULL); /* While we are at it, remember the output section. If we don't access the string data section the section won't be in the output file. So it is sufficient to do the work here. */ file->scninfo[symrunp->scndx].outscnndx = head->scnidx; } /* Get the symbol information. This provides us the offset into the string data section. */ XElf_Sym_vardef (sym); xelf_getsym (locsymdata, symrunp->symidx, sym); assert (sym != NULL); /* Get the data from the file. Using the raw section data here is possible since we don't interpret the string themselves except for looking for the wide NUL character. The NUL character has fortunately the same representation regardless of the byte order. */ symrunp->merge.handle = ebl_wstrtabadd (mergestrtab, (wchar_t *) ((char *) locdata->d_buf + sym->st_value), 0); } while ((symrunp = symrunp->next_in_scn) != runp->symbols); /* All strings have been added. Create the final table. */ ebl_wstrtabfinalize (mergestrtab, outdata); /* Compute the final offsets in the section. */ symrunp = runp->symbols; do { symrunp->merge.value = ebl_wstrtaboffset (symrunp->merge.handle); symrunp->merged = 1; } while ((symrunp = symrunp->next_in_scn) != runp->symbols); /* We don't need the string table anymore. */ ebl_wstrtabfree (mergestrtab); } else { /* Non-standard merging. */ struct Ebl_GStrtab *mergestrtab; struct symbol *symrunp; Elf_Data *locsymdata = NULL; Elf_Data *locdata = NULL; /* If this is no string section the length of each "string" is always one. */ unsigned int len = (head->flags & SHF_STRINGS) ? 0 : 1; /* This is the generic string table functionality. Much slower than the specialized code. */ mergestrtab = ebl_gstrtabinit (SCNINFO_SHDR (head->last->shdr).sh_entsize, false); symrunp = runp->symbols; file = NULL; do { /* Accelarate the loop. We cache the file information since it might very well be the case that the previous entry was from the same file. */ if (symrunp->file != file) { /* Remember the file. */ file = symrunp->file; /* Symbol table data from that file. */ locsymdata = file->symtabdata; /* String section data. */ locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn, NULL); assert (locdata != NULL); /* While we are at it, remember the output section. If we don't access the string data section the section won't be in the output file. So it is sufficient to do the work here. */ file->scninfo[symrunp->scndx].outscnndx = head->scnidx; } /* Get the symbol information. This provides us the offset into the string data section. */ XElf_Sym_vardef (sym); xelf_getsym (locsymdata, symrunp->symidx, sym); assert (sym != NULL); /* Get the data from the file. Using the raw section data here is possible since we don't interpret the string themselves except for looking for the wide NUL character. The NUL character has fortunately the same representation regardless of the byte order. */ symrunp->merge.handle = ebl_gstrtabadd (mergestrtab, (char *) locdata->d_buf + sym->st_value, len); } while ((symrunp = symrunp->next_in_scn) != runp->symbols); /* Create the final table. */ ebl_gstrtabfinalize (mergestrtab, outdata); /* Compute the final offsets in the section. */ symrunp = runp->symbols; do { symrunp->merge.value = ebl_gstrtaboffset (symrunp->merge.handle); symrunp->merged = 1; } while ((symrunp = symrunp->next_in_scn) != runp->symbols); /* We don't need the string table anymore. */ ebl_gstrtabfree (mergestrtab); } } else { no_merge: assert (head->scnidx == elf_ndxscn (scn)); /* It is important to start with the first list entry (and not just any one) to add the sections in the correct order. */ runp = head->last->next; offset = 0; do { Elf_Data *outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* Exceptional case: if we synthesize a data block SCN is NULL and the sectio header info must be for a SHT_NOBITS block and the size and alignment are filled in. */ if (likely (runp->scn != NULL)) { data = elf_getdata (runp->scn, NULL); assert (data != NULL); /* We reuse the data buffer in the input file. */ *outdata = *data; /* Given that we read the input file from disk we know there cannot be another data part. */ assert (elf_getdata (runp->scn, data) == NULL); } else { /* Must be a NOBITS section. */ assert (SCNINFO_SHDR (runp->shdr).sh_type == SHT_NOBITS); outdata->d_buf = NULL; /* Not needed. */ outdata->d_type = ELF_T_BYTE; outdata->d_version = EV_CURRENT; outdata->d_size = SCNINFO_SHDR (runp->shdr).sh_size; outdata->d_align = SCNINFO_SHDR (runp->shdr).sh_addralign; } XElf_Off align = MAX (1, outdata->d_align); assert (powerof2 (align)); offset = ((offset + align - 1) & ~(align - 1)); runp->offset = offset; runp->outscnndx = head->scnidx; runp->allsectionsidx = cnt; outdata->d_off = offset; offset += outdata->d_size; } while ((runp = runp->next) != head->last->next); /* If necessary add the additional line to the .comment section. */ if (ld_state.add_ld_comment && head->flags == 0 && head->type == SHT_PROGBITS && strcmp (head->name, ".comment") == 0 && head->entsize == 0) { Elf_Data *outdata = elf_newdata (scn); if (outdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); outdata->d_buf = (void *) "\0ld (" PACKAGE_NAME ") " PACKAGE_VERSION; outdata->d_size = strlen ((char *) outdata->d_buf + 1) + 2; outdata->d_off = offset; outdata->d_type = ELF_T_BYTE; outdata->d_align = 1; } /* XXX We should create a .comment section if none exists. This requires that we early on detect that no such section exists. This should probably be implemented together with some merging of the section contents. Currently identical entries are not merged. */ } } /* The table we collect the strings in. */ strtab = ebl_strtabinit (true); if (strtab == NULL) error (EXIT_FAILURE, errno, gettext ("cannot create string table")); #ifndef NDEBUG /* Keep track of the use of the XINDEX. */ need_xndx = false; #endif /* We we generate a normal symbol table for an executable and the --export-dynamic option is not given, we need an extra table which keeps track of the symbol entry belonging to the symbol table entry. Note that EXPORT_ALL_DYNAMIC is always set if we generate a DSO so we do not have to test this separately. */ ndxtosym = (struct symbol **) xcalloc (nsym_allocated, sizeof (struct symbol)); /* Create the special symbol for the GOT section. */ if (ld_state.got_symbol != NULL) { assert (nsym < nsym_allocated); // XXX Fix so that it works even if no PLT is needed. fillin_special_symbol (ld_state.got_symbol, ld_state.gotpltscnidx, nsym++, symdata, strtab); } /* Similarly for the dynamic section symbol. */ if (ld_state.dyn_symbol != NULL) { assert (nsym < nsym_allocated); fillin_special_symbol (ld_state.dyn_symbol, ld_state.dynamicscnidx, nsym++, symdata, strtab); } /* Create symbol table entries for the symbols defined in the linker script. */ if (ld_state.lscript_syms != NULL) { struct symbol *rsym = ld_state.lscript_syms; do { assert (nsym < nsym_allocated); fillin_special_symbol (rsym, SHN_ABS, nsym++, symdata, strtab); } while ((rsym = rsym->next) != NULL); } /* Iterate over all input files to collect the symbols. */ file = ld_state.relfiles->next; symdata = elf_getdata (elf_getscn (ld_state.outelf, ld_state.symscnidx), NULL); do { size_t maxcnt; Elf_Data *insymdata; Elf_Data *inxndxdata; /* There must be no dynamic symbol table when creating relocatable files. */ assert (ld_state.file_type != relocatable_file_type || file->dynsymtabdata == NULL); insymdata = file->symtabdata; assert (insymdata != NULL); inxndxdata = file->xndxdata; maxcnt = file->nsymtab; file->symindirect = (Elf32_Word *) xcalloc (maxcnt, sizeof (Elf32_Word)); /* The dynamic symbol table does not contain local symbols. So we skip those entries. */ for (cnt = ld_state.need_symtab ? 1 : file->nlocalsymbols; cnt < maxcnt; ++cnt) { XElf_Sym_vardef (sym); Elf32_Word xndx; struct symbol *defp = NULL; xelf_getsymshndx (insymdata, inxndxdata, cnt, sym, xndx); assert (sym != NULL); if (unlikely (XELF_ST_TYPE (sym->st_info) == STT_SECTION)) { /* Section symbols should always be local but who knows... */ if (ld_state.need_symtab) { /* Determine the real section index in the source file. Use the XINDEX section content if necessary. We don't add this information to the dynamic symbol table. */ if (sym->st_shndx != SHN_XINDEX) xndx = sym->st_shndx; assert (file->scninfo[xndx].allsectionsidx < ld_state.nallsections); file->symindirect[cnt] = ld_state.allsections[file->scninfo[xndx].allsectionsidx]->scnsymidx; /* Note that the resulting index can be zero here. There is no guarantee that the output file will contain all the sections the input file did. */ } continue; } if ((ld_state.strip >= strip_all || !ld_state.need_symtab) /* XXX Do we need these entries? */ && XELF_ST_TYPE (sym->st_info) == STT_FILE) continue; #if NATIVE_ELF != 0 /* Copy old data. We create a temporary copy because the symbol might still be discarded. */ XElf_Sym sym_mem; sym_mem = *sym; sym = &sym_mem; #endif if (sym->st_shndx != SHN_UNDEF && (sym->st_shndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)) { /* If we are creating an executable with no normal symbol table and we do not export all symbols and this symbol is not defined in a DSO as well, ignore it. */ if (!ld_state.export_all_dynamic && !ld_state.need_symtab) { assert (cnt >= file->nlocalsymbols); defp = file->symref[cnt]; assert (defp != NULL); if (!defp->in_dso) /* Ignore it. */ continue; } /* Determine the real section index in the source file. Use the XINDEX section content if necessary. */ if (sym->st_shndx != SHN_XINDEX) xndx = sym->st_shndx; sym->st_value += file->scninfo[xndx].offset; assert (file->scninfo[xndx].outscnndx < SHN_LORESERVE || file->scninfo[xndx].outscnndx > SHN_HIRESERVE); if (unlikely (file->scninfo[xndx].outscnndx > SHN_LORESERVE)) { /* It is not possible to have an extended section index table for the dynamic symbol table. */ if (!ld_state.need_symtab) error (EXIT_FAILURE, 0, gettext ("\ section index too large in dynamic symbol table")); assert (xndxdata != NULL); sym->st_shndx = SHN_XINDEX; xndx = file->scninfo[xndx].outscnndx; #ifndef NDEBUG need_xndx = true; #endif } else { sym->st_shndx = file->scninfo[xndx].outscnndx; xndx = 0; } } else if (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_UNDEF) { /* Check whether we have a (real) definition for this symbol. If this is the case we skip this symbol table entry. */ assert (cnt >= file->nlocalsymbols); defp = file->symref[cnt]; assert (defp != NULL); assert (sym->st_shndx != SHN_COMMON || defp->defined); if ((sym->st_shndx == SHN_COMMON && !defp->common) || (sym->st_shndx == SHN_UNDEF && defp->defined) || defp->added) /* Ignore this symbol table entry, there is a "better" one or we already added it. */ continue; /* Remember that we already added this symbol. */ defp->added = 1; /* Adjust the section number for common symbols. */ if (sym->st_shndx == SHN_COMMON) { sym->st_value = (ld_state.common_section->offset + file->symref[cnt]->merge.value); assert (ld_state.common_section->outscnndx < SHN_LORESERVE); sym->st_shndx = ld_state.common_section->outscnndx; xndx = 0; } } else if (unlikely (sym->st_shndx != SHN_ABS)) { if (SPECIAL_SECTION_NUMBER_P (&ld_state, sym->st_shndx)) /* XXX Add code to handle machine specific special sections. */ abort (); } /* Add the symbol name to the string table. If the user chooses the highest level of stripping avoid adding names for local symbols in the string table. */ if (sym->st_name != 0 && (ld_state.strip < strip_everything || XELF_ST_BIND (sym->st_info) != STB_LOCAL)) symstrent[nsym] = ebl_strtabadd (strtab, elf_strptr (file->elf, file->symstridx, sym->st_name), 0); /* Once we know the name this field will get the correct offset. For now set it to zero which means no name associated. */ GElf_Word st_name = sym->st_name; sym->st_name = 0; /* If we had to merge sections we have a completely new offset for the symbol. */ if (file->has_merge_sections && file->symref[cnt] != NULL && file->symref[cnt]->merged) sym->st_value = file->symref[cnt]->merge.value; /* Create the record in the output sections. */ assert (nsym < nsym_allocated); xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 1); /* Add the reference to the symbol record in case we need it. Find the symbol if this has not happened yet. We do not need the information for local symbols. */ if (defp == NULL && cnt >= file->nlocalsymbols) { defp = file->symref[cnt]; if (defp == NULL) { /* This is a symbol in a discarded COMDAT section. Find the definition we actually use. */ // XXX The question is: do we have to do this here // XXX or can we do it earlier when we discard the // XXX section. struct symbol search; search.name = elf_strptr (file->elf, file->symstridx, st_name); struct symbol *realp = ld_symbol_tab_find (&ld_state.symbol_tab, elf_hash (search.name), &search); if (realp == NULL) // XXX What to do here? error (EXIT_FAILURE, 0, "couldn't find symbol from COMDAT section"); file->symref[cnt] = realp; continue; } } /* Store the reference to the symbol record. The sorting code will have to keep this array in the correct order, too. */ ndxtosym[nsym] = defp; /* One more entry finished. */ if (cnt >= file->nlocalsymbols) { assert (file->symref[cnt]->outsymidx == 0); file->symref[cnt]->outsymidx = nsym; } file->symindirect[cnt] = nsym++; } } while ((file = file->next) != ld_state.relfiles->next); /* Make sure we didn't create the extended section index table for nothing. */ assert (xndxdata == NULL || need_xndx); /* Create the version related sections. */ if (ld_state.verneedscnidx != 0) { /* We know the number of input files and total number of referenced versions. This allows us to allocate the memory and then we iterate over the DSOs to get the version information. */ struct usedfiles *runp; runp = ld_state.dsofiles->next; do allocate_version_names (runp, dynstrtab); while ((runp = runp->next) != ld_state.dsofiles->next); if (ld_state.needed != NULL) { runp = ld_state.needed->next; do allocate_version_names (runp, dynstrtab); while ((runp = runp->next) != ld_state.needed->next); } } /* At this point we should hide symbols and so on. */ if (ld_state.default_bind_local || ld_state.version_str_tab.filled > 0) /* XXX Add one more test when handling of wildcard symbol names is supported. */ { /* Check all non-local symbols whether they are on the export list. */ bool any_reduced = false; for (cnt = 1; cnt < nsym; ++cnt) { XElf_Sym_vardef (sym); /* Note that we don't have to use 'xelf_getsymshndx' since we only need the binding and the symbol name. */ xelf_getsym (symdata, cnt, sym); assert (sym != NULL); if (reduce_symbol_p (sym, symstrent[cnt])) { // XXX Check whether this is correct... assert (ndxtosym[cnt]->outdynsymidx != 0); ndxtosym[cnt]->outdynsymidx = 0; sym->st_info = XELF_ST_INFO (STB_LOCAL, XELF_ST_TYPE (sym->st_info)); (void) xelf_update_sym (symdata, cnt, sym); /* Show that we don't need this string anymore. */ if (ld_state.strip == strip_everything) { symstrent[cnt] = NULL; any_reduced = true; } } } if (unlikely (any_reduced)) { /* Since we will not write names of local symbols in the output file and we have reduced the binding of some symbols the string table previously constructed contains too many string. Correct it. */ struct Ebl_Strtab *newp = ebl_strtabinit (true); for (cnt = 1; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) symstrent[cnt] = ebl_strtabadd (newp, ebl_string (symstrent[cnt]), 0); ebl_strtabfree (strtab); strtab = newp; } } /* Add the references to DSOs. We can add these entries this late (after sorting out versioning) because references to DSOs are not effected. */ if (ld_state.from_dso != NULL) { struct symbol *runp; size_t plt_base = nsym + ld_state.nfrom_dso - ld_state.nplt; size_t plt_idx = 0; size_t obj_idx = 0; assert (ld_state.nfrom_dso >= ld_state.nplt); runp = ld_state.from_dso; do { // XXX What about functions which are only referenced via // pointers and not PLT entries? Can we distinguish such uses? size_t idx; if (runp->type == STT_FUNC) { /* Store the PLT entry number. */ runp->merge.value = plt_idx + 1; idx = plt_base + plt_idx++; } else idx = nsym + obj_idx++; XElf_Sym_vardef (sym); xelf_getsym_ptr (symdata, idx, sym); sym->st_value = 0; sym->st_size = runp->size; sym->st_info = XELF_ST_INFO (runp->weak ? STB_WEAK : STB_GLOBAL, runp->type); sym->st_other = STV_DEFAULT; sym->st_shndx = SHN_UNDEF; /* Create the record in the output sections. */ xelf_update_symshndx (symdata, xndxdata, idx, sym, 0, 0); const char *name = runp->name; size_t namelen = 0; if (runp->file->verdefdata != NULL) { // XXX Is it useful to add the versym value to struct symbol? XElf_Versym versym; (void) xelf_getversym_copy (runp->file->versymdata, runp->symidx, versym); /* One can only link with the default version. */ assert ((versym & 0x8000) == 0); const char *versname = ebl_string (runp->file->verdefent[versym]); size_t versname_len = strlen (versname) + 1; namelen = strlen (name) + versname_len + 2; char *newp = (char *) obstack_alloc (&ld_state.smem, namelen); memcpy (stpcpy (stpcpy (newp, name), "@@"), versname, versname_len); name = newp; } symstrent[idx] = ebl_strtabadd (strtab, name, namelen); /* Record the initial index in the symbol table. */ runp->outsymidx = idx; /* Remember the symbol record this ELF symbol came from. */ ndxtosym[idx] = runp; } while ((runp = runp->next) != ld_state.from_dso); assert (nsym + obj_idx == plt_base); assert (plt_idx == ld_state.nplt); nsym = plt_base + plt_idx; } /* Now we know how many symbols will be in the output file. Adjust the count in the section data. */ symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym); if (unlikely (xndxdata != NULL)) xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD, nsym); /* Create the symbol string table section. */ strscn = elf_newscn (ld_state.outelf); ld_state.strscnidx = elf_ndxscn (strscn); data = elf_newdata (strscn); xelf_getshdr (strscn, shdr); if (data == NULL || shdr == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* Create a compact string table, allocate the memory for it, and fill in the section data information. */ ebl_strtabfinalize (strtab, data); shdr->sh_type = SHT_STRTAB; assert (shdr->sh_entsize == 0); if (unlikely (xelf_update_shdr (strscn, shdr) == 0)) error (EXIT_FAILURE, 0, gettext ("cannot create section for output file: %s"), elf_errmsg (-1)); /* Fill in the offsets of the symbol names. */ for (cnt = 1; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) { XElf_Sym_vardef (sym); /* Note that we don't have to use 'xelf_getsymshndx' since we don't modify the section index. */ xelf_getsym (symdata, cnt, sym); /* This better worked, we did it before. */ assert (sym != NULL); sym->st_name = ebl_strtaboffset (symstrent[cnt]); (void) xelf_update_sym (symdata, cnt, sym); } /* Since we are going to reorder the symbol table but still have to be able to find the new position based on the old one (since the latter is stored in 'symindirect' information of the input file data structure) we have to create yet another indirection table. */ ld_state.dblindirect = dblindirect = (Elf32_Word *) xmalloc (nsym * sizeof (Elf32_Word)); /* Sort the symbol table so that the local symbols come first. */ /* XXX We don't use stable sorting here. It seems not necessary and would be more expensive. If it turns out to be necessary this can be fixed easily. */ nsym_local = 1; cnt = nsym - 1; while (nsym_local < cnt) { XElf_Sym_vardef (locsym); Elf32_Word locxndx; XElf_Sym_vardef (globsym); Elf32_Word globxndx; do { xelf_getsymshndx (symdata, xndxdata, nsym_local, locsym, locxndx); /* This better works. */ assert (locsym != NULL); if (XELF_ST_BIND (locsym->st_info) != STB_LOCAL && (ld_state.need_symtab || ld_state.export_all_dynamic)) { do { xelf_getsymshndx (symdata, xndxdata, cnt, globsym, globxndx); /* This better works. */ assert (globsym != NULL); if (unlikely (XELF_ST_BIND (globsym->st_info) == STB_LOCAL)) { /* We swap the two entries. */ #if NATIVE_ELF != 0 /* Since we directly modify the data in the ELF data structure we have to make a copy of one of the entries. */ XElf_Sym locsym_copy = *locsym; locsym = &locsym_copy; #endif xelf_update_symshndx (symdata, xndxdata, nsym_local, globsym, globxndx, 1); xelf_update_symshndx (symdata, xndxdata, cnt, locsym, locxndx, 1); /* Also swap the cross references. */ dblindirect[nsym_local] = cnt; dblindirect[cnt] = nsym_local; /* And the entries for the symbol names. */ struct Ebl_Strent *strtmp = symstrent[nsym_local]; symstrent[nsym_local] = symstrent[cnt]; symstrent[cnt] = strtmp; /* And the mapping from symbol table entry to struct symbol record. */ struct symbol *symtmp = ndxtosym[nsym_local]; ndxtosym[nsym_local] = ndxtosym[cnt]; ndxtosym[cnt] = symtmp; /* Go to the next entry. */ ++nsym_local; --cnt; break; } dblindirect[cnt] = cnt; } while (nsym_local < --cnt); break; } dblindirect[nsym_local] = nsym_local; } while (++nsym_local < cnt); } /* The symbol 'nsym_local' is currently pointing to might be local, too. Check and increment the variable if this is the case. */ if (likely (nsym_local < nsym)) { XElf_Sym_vardef (locsym); /* This entry isn't moved. */ dblindirect[nsym_local] = nsym_local; /* Note that it is OK to not use 'xelf_getsymshndx' here. */ xelf_getsym (symdata, nsym_local, locsym); /* This better works. */ assert (locsym != NULL); if (XELF_ST_BIND (locsym->st_info) == STB_LOCAL) ++nsym_local; } /* We need the versym array right away to keep track of the version symbols. */ if (ld_state.versymscnidx != 0) { /* We allocate more memory than we need since the array is morroring the dynamic symbol table and not the normal symbol table. I.e., no local symbols are present. */ versymscn = elf_getscn (ld_state.outelf, ld_state.versymscnidx); versymdata = elf_newdata (versymscn); if (versymdata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create versioning section: %s"), elf_errmsg (-1)); versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF, nsym - nsym_local + 1); versymdata->d_buf = xcalloc (1, versymdata->d_size); versymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_HALF, 1); versymdata->d_off = 0; versymdata->d_type = ELF_T_HALF; } /* If we have to construct the dynamic symbol table we must not include the local symbols. If the normal symbol has to be emitted as well we haven't done anything else yet and we can construct it from scratch now. */ if (unlikely (!ld_state.need_symtab)) { /* Note that the following code works even if there is no entry to remove since the zeroth entry is always local. */ size_t reduce = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_local - 1); XElf_Sym_vardef (nullsym); xelf_getsym_ptr (symdata, nsym_local - 1, nullsym); /* Note that we don't have to use 'xelf_update_symshndx' since this is the dynamic symbol table we write. */ (void) xelf_update_sym (symdata, nsym_local - 1, memset (nullsym, '\0', sizeof (*nullsym))); /* Update the buffer pointer and size in the output data. */ symdata->d_buf = (char *) symdata->d_buf + reduce; symdata->d_size -= reduce; /* Add the version symbol information. */ if (versymdata != NULL) { nsym_dyn = 1; for (cnt = nsym_local; cnt < nsym; ++cnt, ++nsym_dyn) { struct symbol *symp = ndxtosym[cnt]; if (symp->file->versymdata != NULL) { GElf_Versym versym; gelf_getversym (symp->file->versymdata, symp->symidx, &versym); (void) gelf_update_versym (versymdata, symp->outdynsymidx, &symp->file->verdefused[versym]); } } } /* Since we only created the dynamic symbol table the number of dynamic symbols is the total number of symbols. */ nsym_dyn = nsym - nsym_local + 1; /* XXX TBI. Create whatever data structure is missing. */ abort (); } else if (ld_state.need_dynsym) { /* Create the dynamic symbol table section data along with the string table. We look at all non-local symbols we found for the normal symbol table and add those. */ dynsymscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx); dynsymdata = elf_newdata (dynsymscn); dynstrdata = elf_newdata (elf_getscn (ld_state.outelf, ld_state.dynstrscnidx)); if (dynsymdata == NULL || dynstrdata == NULL) error (EXIT_FAILURE, 0, gettext ("\ cannot create dynamic symbol table for output file: %s"), elf_errmsg (-1)); nsym_dyn_allocated = nsym - nsym_local + 1; dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_dyn_allocated); dynsymdata->d_buf = memset (xmalloc (dynsymdata->d_size), '\0', xelf_fsize (ld_state.outelf, ELF_T_SYM, 1)); dynsymdata->d_type = ELF_T_SYM; dynsymdata->d_off = 0; dynsymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); /* We need one more array which contains the hash codes of the symbol names. */ hashcodes = (Elf32_Word *) xcalloc (__builtin_popcount ((int) ld_state.hash_style) * nsym_dyn_allocated, sizeof (Elf32_Word)); gnuhashcodes = hashcodes; if (GENERATE_SYSV_HASH) gnuhashcodes += nsym_dyn_allocated; /* We have and empty entry at the beginning. */ nsym_dyn = 1; /* Populate the table. */ for (cnt = nsym_local; cnt < nsym; ++cnt) { XElf_Sym_vardef (sym); xelf_getsym (symdata, cnt, sym); assert (sym != NULL); if (sym->st_shndx == SHN_XINDEX) error (EXIT_FAILURE, 0, gettext ("\ section index too large in dynamic symbol table")); /* We do not add the symbol to the dynamic symbol table if - the symbol is for a file - it is not externally visible (internal, hidden) - export_all_dynamic is not set and the symbol is only defined in the executable (i.e., it is defined, but not (also) in DSO) Set symstrent[cnt] to NULL in case an entry is ignored. */ if (XELF_ST_TYPE (sym->st_info) == STT_FILE || XELF_ST_VISIBILITY (sym->st_other) == STV_INTERNAL || XELF_ST_VISIBILITY (sym->st_other) == STV_HIDDEN || (!ld_state.export_all_dynamic && !ndxtosym[cnt]->in_dso && ndxtosym[cnt]->defined)) { symstrent[cnt] = NULL; continue; } /* Store the index of the symbol in the dynamic symbol table. This is a preliminary value in case we use the GNU-style hash table. */ ndxtosym[cnt]->outdynsymidx = nsym_dyn; /* Create a new string table entry. */ const char *str = ndxtosym[cnt]->name; symstrent[cnt] = ebl_strtabadd (dynstrtab, str, 0); if (GENERATE_SYSV_HASH) hashcodes[nsym_dyn] = elf_hash (str); if (GENERATE_GNU_HASH) gnuhashcodes[nsym_dyn] = elf_gnu_hash (str); ++nsym_dyn; } if (ld_state.file_type != relocatable_file_type) { /* Finalize the dynamic string table. */ ebl_strtabfinalize (dynstrtab, dynstrdata); assert (ld_state.hashscnidx != 0 || ld_state.gnuhashscnidx != 0); /* Create the GNU-style hash table. */ if (GENERATE_GNU_HASH) create_gnu_hash (nsym_local, nsym, nsym_dyn, gnuhashcodes); /* Create the SysV-style hash table. This has to happen after the GNU-style table is created since CREATE-GNU-HASH might reorder the dynamic symbol table. */ if (GENERATE_SYSV_HASH) create_hash (nsym_local, nsym, nsym_dyn, hashcodes); } /* Add the version information. */ if (versymdata != NULL) for (cnt = nsym_local; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) { struct symbol *symp = ndxtosym[cnt]; /* Synthetic symbols (i.e., those with no file attached) have no version information. */ if (symp->file != NULL && symp->file->verdefdata != NULL) { GElf_Versym versym; gelf_getversym (symp->file->versymdata, symp->symidx, &versym); (void) gelf_update_versym (versymdata, symp->outdynsymidx, &symp->file->verdefused[versym]); } else { /* XXX Add support for version definitions. */ GElf_Versym global = VER_NDX_GLOBAL; (void) gelf_update_versym (versymdata, nsym_dyn, &global); } } /* Update the information about the symbol section. */ if (versymdata != NULL) { /* Correct the size now that we know how many entries the dynamic symbol table has. */ versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF, nsym_dyn); /* Add the reference to the symbol table. */ xelf_getshdr (versymscn, shdr); assert (shdr != NULL); shdr->sh_link = ld_state.dynsymscnidx; (void) xelf_update_shdr (versymscn, shdr); } } if (ld_state.file_type != relocatable_file_type) { /* Now put the names in. */ for (cnt = nsym_local; cnt < nsym; ++cnt) if (symstrent[cnt] != NULL) { XElf_Sym_vardef (sym); size_t dynidx = ndxtosym[cnt]->outdynsymidx; #if NATIVE_ELF != 0 XElf_Sym *osym; memcpy (xelf_getsym (dynsymdata, dynidx, sym), xelf_getsym (symdata, cnt, osym), sizeof (XElf_Sym)); #else xelf_getsym (symdata, cnt, sym); assert (sym != NULL); #endif sym->st_name = ebl_strtaboffset (symstrent[cnt]); (void) xelf_update_sym (dynsymdata, dynidx, sym); } free (hashcodes); /* Create the required version section. */ if (ld_state.verneedscnidx != 0) { Elf_Scn *verneedscn; Elf_Data *verneeddata; struct usedfiles *runp; size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1); size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1); size_t offset; int ntotal; verneedscn = elf_getscn (ld_state.outelf, ld_state.verneedscnidx); xelf_getshdr (verneedscn, shdr); verneeddata = elf_newdata (verneedscn); if (shdr == NULL || verneeddata == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create versioning data: %s"), elf_errmsg (-1)); verneeddata->d_size = (ld_state.nverdeffile * verneed_size + ld_state.nverdefused * vernaux_size); verneeddata->d_buf = xmalloc (verneeddata->d_size); verneeddata->d_type = ELF_T_VNEED; verneeddata->d_align = xelf_fsize (ld_state.outelf, ELF_T_WORD, 1); verneeddata->d_off = 0; offset = 0; ntotal = ld_state.nverdeffile; runp = ld_state.dsofiles->next; do { offset = create_verneed_data (offset, verneeddata, runp, &ntotal); runp = runp->next; } while (ntotal > 0 && runp != ld_state.dsofiles->next); if (ntotal > 0) { runp = ld_state.needed->next; do { offset = create_verneed_data (offset, verneeddata, runp, &ntotal); runp = runp->next; } while (ntotal > 0 && runp != ld_state.needed->next); } assert (offset == verneeddata->d_size); /* Add the needed information to the section header. */ shdr->sh_link = ld_state.dynstrscnidx; shdr->sh_info = ld_state.nverdeffile; (void) xelf_update_shdr (verneedscn, shdr); } /* Adjust the section size. */ dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_dyn); if (versymdata != NULL) versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF, nsym_dyn); /* Add the remaining information to the section header. */ xelf_getshdr (dynsymscn, shdr); /* There is always exactly one local symbol. */ shdr->sh_info = 1; /* Reference the string table. */ shdr->sh_link = ld_state.dynstrscnidx; /* Write the updated info back. */ (void) xelf_update_shdr (dynsymscn, shdr); } /* We don't need the string table anymore. */ free (symstrent); /* Remember the total number of symbols in the dynamic symbol table. */ ld_state.ndynsym = nsym_dyn; /* Fill in the section header information. */ symscn = elf_getscn (ld_state.outelf, ld_state.symscnidx); xelf_getshdr (symscn, shdr); if (shdr == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create symbol table for output file: %s"), elf_errmsg (-1)); shdr->sh_type = SHT_SYMTAB; shdr->sh_link = ld_state.strscnidx; shdr->sh_info = nsym_local; shdr->sh_entsize = xelf_fsize (ld_state.outelf, ELF_T_SYM, 1); (void) xelf_update_shdr (symscn, shdr); /* Add names for the generated sections. */ if (ld_state.symscnidx != 0) symtab_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab", 8); if (ld_state.xndxscnidx != 0) xndx_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab_shndx", 14); if (ld_state.strscnidx != 0) strtab_ent = ebl_strtabadd (ld_state.shstrtab, ".strtab", 8); /* At this point we would have to test for failures in the allocation. But we skip this. First, the problem will be caught later when doing more allocations for the section header table. Even if this would not be the case all that would happen is that the section names are empty. The binary would still be usable if it is an executable or a DSO. Not adding the test here saves quite a bit of code. */ /* Finally create the section for the section header string table. */ shstrtab_scn = elf_newscn (ld_state.outelf); shstrtab_ndx = elf_ndxscn (shstrtab_scn); if (unlikely (shstrtab_ndx == SHN_UNDEF)) error (EXIT_FAILURE, 0, gettext ("cannot create section header string section: %s"), elf_errmsg (-1)); /* Add the name of the section to the string table. */ shstrtab_ent = ebl_strtabadd (ld_state.shstrtab, ".shstrtab", 10); if (unlikely (shstrtab_ent == NULL)) error (EXIT_FAILURE, errno, gettext ("cannot create section header string section")); /* Finalize the section header string table. */ data = elf_newdata (shstrtab_scn); if (data == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section header string section: %s"), elf_errmsg (-1)); ebl_strtabfinalize (ld_state.shstrtab, data); /* Now we know the string offsets for all section names. */ for (cnt = 0; cnt < ld_state.nallsections; ++cnt) if (ld_state.allsections[cnt]->scnidx != 0) { Elf_Scn *scn; scn = elf_getscn (ld_state.outelf, ld_state.allsections[cnt]->scnidx); xelf_getshdr (scn, shdr); assert (shdr != NULL); shdr->sh_name = ebl_strtaboffset (ld_state.allsections[cnt]->nameent); if (xelf_update_shdr (scn, shdr) == 0) assert (0); } /* Add the names for the generated sections to the respective section headers. */ if (symtab_ent != NULL) { Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.symscnidx); xelf_getshdr (scn, shdr); /* This cannot fail, we already accessed the header before. */ assert (shdr != NULL); shdr->sh_name = ebl_strtaboffset (symtab_ent); (void) xelf_update_shdr (scn, shdr); } if (xndx_ent != NULL) { Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.xndxscnidx); xelf_getshdr (scn, shdr); /* This cannot fail, we already accessed the header before. */ assert (shdr != NULL); shdr->sh_name = ebl_strtaboffset (xndx_ent); (void) xelf_update_shdr (scn, shdr); } if (strtab_ent != NULL) { Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.strscnidx); xelf_getshdr (scn, shdr); /* This cannot fail, we already accessed the header before. */ assert (shdr != NULL); shdr->sh_name = ebl_strtaboffset (strtab_ent); (void) xelf_update_shdr (scn, shdr); } /* And the section header table section itself. */ xelf_getshdr (shstrtab_scn, shdr); if (shdr == NULL) error (EXIT_FAILURE, 0, gettext ("cannot create section header string section: %s"), elf_errmsg (-1)); shdr->sh_name = ebl_strtaboffset (shstrtab_ent); shdr->sh_type = SHT_STRTAB; if (unlikely (xelf_update_shdr (shstrtab_scn, shdr) == 0)) error (EXIT_FAILURE, 0, gettext ("cannot create section header string section: %s"), elf_errmsg (-1)); /* Add the correct section header info to the section group sections. */ groups = ld_state.groups; while (groups != NULL) { Elf_Scn *scn = elf_getscn (ld_state.outelf, groups->outscnidx); xelf_getshdr (scn, shdr); assert (shdr != NULL); shdr->sh_name = ebl_strtaboffset (groups->nameent); shdr->sh_type = SHT_GROUP; shdr->sh_flags = 0; shdr->sh_link = ld_state.symscnidx; shdr->sh_entsize = sizeof (Elf32_Word); /* Determine the index for the signature symbol. */ Elf32_Word si = groups->symbol->file->symindirect[groups->symbol->symidx]; if (si == 0) { assert (groups->symbol->file->symref[groups->symbol->symidx] != NULL); si = groups->symbol->file->symref[groups->symbol->symidx]->outsymidx; assert (si != 0); } shdr->sh_info = ld_state.dblindirect[si]; (void) xelf_update_shdr (scn, shdr); struct scngroup *oldp = groups; groups = groups->next; free (oldp); } if (ld_state.file_type != relocatable_file_type) { /* Every executable needs a program header. The number of entries varies. One exists for each segment. Each SHT_NOTE section gets one, too. For dynamically linked executables we have to create one for the program header, the interpreter, and the dynamic section. First count the number of segments. XXX Determine whether the segment is non-empty. */ size_t nphdr = 0; /* We always add a PT_GNU_stack entry. */ ++nphdr; struct output_segment *segment = ld_state.output_segments; while (segment != NULL) { ++nphdr; segment = segment->next; } /* Add the number of SHT_NOTE sections. We counted them earlier. */ nphdr += ld_state.nnotesections; /* If we create a DSO or the file is linked against DSOs we have at least one more entry: DYNAMIC. If an interpreter is specified we add PHDR and INTERP, too. */ if (dynamically_linked_p ()) { ++nphdr; if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) nphdr += 2; } /* If we need a TLS segment we need an entry for that. */ if (ld_state.need_tls) ++nphdr; /* Create the program header structure. */ XElf_Phdr_vardef (phdr); if (xelf_newphdr (ld_state.outelf, nphdr) == 0) error (EXIT_FAILURE, 0, gettext ("cannot create program header: %s"), elf_errmsg (-1)); /* Determine the section sizes and offsets. We have to do this to be able to determine the memory layout (which normally differs from the file layout). */ if (elf_update (ld_state.outelf, ELF_C_NULL) == -1) error (EXIT_FAILURE, 0, gettext ("while determining file layout: %s"), elf_errmsg (-1)); /* Now determine the memory addresses of all the sections and segments. */ Elf32_Word nsec = 0; Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.allsections[nsec]->scnidx); xelf_getshdr (scn, shdr); assert (shdr != NULL); /* The address we start with is the offset of the first (not zeroth) section. */ XElf_Addr addr = shdr->sh_offset; XElf_Addr tls_offset = 0; XElf_Addr tls_start = ~((XElf_Addr) 0); XElf_Addr tls_end = 0; XElf_Off tls_filesize = 0; XElf_Addr tls_align = 0; /* The index of the first loadable segment. */ nphdr = 0; if (dynamically_linked_p ()) { ++nphdr; if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) nphdr += 2; } segment = ld_state.output_segments; while (segment != NULL) { struct output_rule *orule; bool first_section = true; XElf_Off nobits_size = 0; XElf_Off memsize = 0; /* The minimum alignment is a page size. */ segment->align = ld_state.pagesize; for (orule = segment->output_rules; orule != NULL; orule = orule->next) if (orule->tag == output_section) { /* See whether this output rule corresponds to the next section. Yes, this is a pointer comparison. */ if (ld_state.allsections[nsec]->name != orule->val.section.name) /* No, ignore this output rule. */ continue; /* We assign addresses only in segments which are actually loaded. */ if (segment->mode != 0) { /* Adjust the offset of the input sections. */ struct scninfo *isect; struct scninfo *first; isect = first = ld_state.allsections[nsec]->last; if (isect != NULL) do isect->offset += addr; while ((isect = isect->next) != first); /* Set the address of current section. */ shdr->sh_addr = addr; /* Write the result back. */ (void) xelf_update_shdr (scn, shdr); /* Remember the address. */ ld_state.allsections[nsec]->addr = addr; /* Handle TLS sections. */ if (unlikely (shdr->sh_flags & SHF_TLS)) { if (tls_start > addr) { tls_start = addr; tls_offset = shdr->sh_offset; } if (tls_end < addr + shdr->sh_size) tls_end = addr + shdr->sh_size; if (shdr->sh_type != SHT_NOBITS) tls_filesize += shdr->sh_size; if (shdr->sh_addralign > tls_align) tls_align = shdr->sh_addralign; } } if (first_section) { /* The first segment starts at offset zero. */ if (segment == ld_state.output_segments) { segment->offset = 0; segment->addr = addr - shdr->sh_offset; } else { segment->offset = shdr->sh_offset; segment->addr = addr; } /* Determine the maximum alignment requirement. */ segment->align = MAX (segment->align, shdr->sh_addralign); first_section = false; } /* NOBITS TLS sections are not laid out in address space along with the other sections. */ if (shdr->sh_type != SHT_NOBITS || (shdr->sh_flags & SHF_TLS) == 0) { memsize = (shdr->sh_offset - segment->offset + shdr->sh_size); if (nobits_size != 0 && shdr->sh_type != SHT_NOTE) error (EXIT_FAILURE, 0, gettext ("\ internal error: non-nobits section follows nobits section")); if (shdr->sh_type == SHT_NOBITS) nobits_size += shdr->sh_size; } /* Determine the new address which is computed using the difference of the offsets on the sections. Note that this assumes that the sections following each other in the section header table are also consecutive in the file. This is true here because libelf constructs files this way. */ XElf_Off oldoff = shdr->sh_offset; if (++nsec >= ld_state.nallsections) break; scn = elf_getscn (ld_state.outelf, ld_state.allsections[nsec]->scnidx); xelf_getshdr (scn, shdr); assert (shdr != NULL); /* This is the new address resulting from the offsets in the file. */ assert (oldoff <= shdr->sh_offset); addr += shdr->sh_offset - oldoff; } else { assert (orule->tag == output_assignment); if (strcmp (orule->val.assignment->variable, ".") == 0) /* This is a change of the address. */ addr = eval_expression (orule->val.assignment->expression, addr); else if (orule->val.assignment->sym != NULL) { /* This symbol is used. Update the symbol table entry. */ XElf_Sym_vardef (sym); size_t idx; /* Note that we do not have to use xelf_getsymshndx since we only update the symbol address, not the section information. */ idx = dblindirect[orule->val.assignment->sym->outsymidx]; xelf_getsym (symdata, idx, sym); sym->st_value = addr; (void) xelf_update_sym (symdata, idx, sym); idx = orule->val.assignment->sym->outdynsymidx; if (idx != 0) { assert (dynsymdata != NULL); xelf_getsym (dynsymdata, idx, sym); sym->st_value = addr; (void) xelf_update_sym (dynsymdata, idx, sym); } } } /* Store the segment parameter for loadable segments. */ if (segment->mode != 0) { xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr); phdr->p_type = PT_LOAD; phdr->p_offset = segment->offset; phdr->p_vaddr = segment->addr; phdr->p_paddr = phdr->p_vaddr; phdr->p_filesz = memsize - nobits_size; phdr->p_memsz = memsize; phdr->p_flags = segment->mode; phdr->p_align = segment->align; (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr); ++nphdr; } segment = segment->next; } /* Create the other program header entries. */ xelf_getehdr (ld_state.outelf, ehdr); assert (ehdr != NULL); /* Add the TLS information. */ if (ld_state.need_tls) { xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr); phdr->p_type = PT_TLS; phdr->p_offset = tls_offset; phdr->p_vaddr = tls_start; phdr->p_paddr = tls_start; phdr->p_filesz = tls_filesize; phdr->p_memsz = tls_end - tls_start; phdr->p_flags = PF_R; phdr->p_align = tls_align; ld_state.tls_tcb = tls_end; ld_state.tls_start = tls_start; (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr); ++nphdr; } /* Add the stack information. */ xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr); phdr->p_type = PT_GNU_STACK; phdr->p_offset = 0; phdr->p_vaddr = 0; phdr->p_paddr = 0; phdr->p_filesz = 0; phdr->p_memsz = 0; phdr->p_flags = (PF_R | PF_W | (ld_state.execstack == execstack_true ? PF_X : 0)); phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr); ++nphdr; /* Adjust the addresses in the address fields of the symbol records according to the load addresses of the sections. */ if (ld_state.need_symtab) for (cnt = 1; cnt < nsym; ++cnt) { XElf_Sym_vardef (sym); Elf32_Word shndx; xelf_getsymshndx (symdata, xndxdata, cnt, sym, shndx); assert (sym != NULL); if (sym->st_shndx != SHN_XINDEX) shndx = sym->st_shndx; if ((shndx > SHN_UNDEF && shndx < SHN_LORESERVE) || shndx > SHN_HIRESERVE) { /* Note we subtract 1 from the section index since ALLSECTIONS does not store the dummy section with offset zero. */ sym->st_value += ld_state.allsections[shndx - 1]->addr; /* We don't have to use 'xelf_update_symshndx' since the section number doesn't change. */ (void) xelf_update_sym (symdata, cnt, sym); } } if (ld_state.need_dynsym) for (cnt = 1; cnt < nsym_dyn; ++cnt) { XElf_Sym_vardef (sym); xelf_getsym (dynsymdata, cnt, sym); assert (sym != NULL); if (sym->st_shndx > SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) { /* Note we subtract 1 from the section index since ALLSECTIONS does not store the dummy section with offset zero. */ sym->st_value += ld_state.allsections[sym->st_shndx - 1]->addr; /* We don't have to use 'xelf_update_symshndx' since the section number doesn't change. */ (void) xelf_update_sym (dynsymdata, cnt, sym); } } /* Now is a good time to determine the values of all the symbols we encountered. */ // XXX This loop is very inefficient. The hash tab iterator also // returns all symbols in DSOs. struct symbol *se; void *p = NULL; while ((se = ld_symbol_tab_iterate (&ld_state.symbol_tab, &p)) != NULL) if (! se->in_dso) { XElf_Sym_vardef (sym); addr = 0; if (se->outdynsymidx != 0) { xelf_getsym (dynsymdata, se->outdynsymidx, sym); assert (sym != NULL); addr = sym->st_value; } else if (se->outsymidx != 0) { assert (dblindirect[se->outsymidx] != 0); xelf_getsym (symdata, dblindirect[se->outsymidx], sym); assert (sym != NULL); addr = sym->st_value; } else abort (); se->merge.value = addr; } /* Complete the header of the .rel.dyn/.rela.dyn section. Point to the symbol table. The sh_info field is left zero since there is no specific section the contained relocations are for. */ if (ld_state.reldynscnidx != 0) { assert (ld_state.dynsymscnidx != 0); scn = elf_getscn (ld_state.outelf, ld_state.reldynscnidx); xelf_getshdr (scn, shdr); assert (shdr != NULL); shdr->sh_link = ld_state.dynsymscnidx; (void) xelf_update_shdr (scn, shdr); } /* Fill in the dynamic segment/section. */ if (dynamically_linked_p ()) { Elf_Scn *outscn; int idx = 0; if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) { assert (ld_state.interpscnidx != 0); xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.interpscnidx), shdr); assert (shdr != NULL); xelf_getphdr_ptr (ld_state.outelf, idx, phdr); phdr->p_type = PT_PHDR; phdr->p_offset = ehdr->e_phoff; phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset; phdr->p_paddr = phdr->p_vaddr; phdr->p_filesz = ehdr->e_phnum * ehdr->e_phentsize; phdr->p_memsz = phdr->p_filesz; phdr->p_flags = 0; /* No need to set PF_R or so. */ phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); (void) xelf_update_phdr (ld_state.outelf, idx, phdr); ++idx; /* The interpreter string. */ xelf_getphdr_ptr (ld_state.outelf, idx, phdr); phdr->p_type = PT_INTERP; phdr->p_offset = shdr->sh_offset; phdr->p_vaddr = shdr->sh_addr; phdr->p_paddr = phdr->p_vaddr; phdr->p_filesz = shdr->sh_size; phdr->p_memsz = phdr->p_filesz; phdr->p_flags = 0; /* No need to set PF_R or so. */ phdr->p_align = 1; /* It's a string. */ (void) xelf_update_phdr (ld_state.outelf, idx, phdr); ++idx; } /* The pointer to the dynamic section. We this we need to get the information for the dynamic section first. */ assert (ld_state.dynamicscnidx); outscn = elf_getscn (ld_state.outelf, ld_state.dynamicscnidx); xelf_getshdr (outscn, shdr); assert (shdr != NULL); xelf_getphdr_ptr (ld_state.outelf, idx, phdr); phdr->p_type = PT_DYNAMIC; phdr->p_offset = shdr->sh_offset; phdr->p_vaddr = shdr->sh_addr; phdr->p_paddr = phdr->p_vaddr; phdr->p_filesz = shdr->sh_size; phdr->p_memsz = phdr->p_filesz; phdr->p_flags = 0; /* No need to set PF_R or so. */ phdr->p_align = shdr->sh_addralign; (void) xelf_update_phdr (ld_state.outelf, idx, phdr); /* Fill in the reference to the .dynstr section. */ assert (ld_state.dynstrscnidx != 0); shdr->sh_link = ld_state.dynstrscnidx; (void) xelf_update_shdr (outscn, shdr); /* And fill the remaining entries. */ Elf_Data *dyndata = elf_getdata (outscn, NULL); assert (dyndata != NULL); /* Add the DT_NEEDED entries. */ if (ld_state.ndsofiles > 0) { struct usedfiles *runp = ld_state.dsofiles->next; do if (runp->used || !runp->as_needed) { /* Add the position-dependent flag if necessary. */ if (runp->lazyload) new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_POSFLAG_1, DF_P1_LAZYLOAD); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_NEEDED, ebl_strtaboffset (runp->sonameent)); } while ((runp = runp->next) != ld_state.dsofiles->next); } /* We can finish the DT_RUNPATH/DT_RPATH entries now. */ if (ld_state.rxxpath_strent != NULL) new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, ld_state.rxxpath_tag, ebl_strtaboffset (ld_state.rxxpath_strent)); /* Reference to initialization and finalization functions. */ // XXX This code depends on symbol table being relocated. if (ld_state.init_symbol != NULL) { XElf_Sym_vardef (sym); if (ld_state.need_symtab) xelf_getsym (symdata, dblindirect[ld_state.init_symbol->outsymidx], sym); else xelf_getsym (dynsymdata, ld_state.init_symbol->outdynsymidx, sym); assert (sym != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_INIT, sym->st_value); } if (ld_state.fini_symbol != NULL) { XElf_Sym_vardef (sym); if (ld_state.need_symtab) xelf_getsym (symdata, dblindirect[ld_state.fini_symbol->outsymidx], sym); else xelf_getsym (dynsymdata, ld_state.fini_symbol->outdynsymidx, sym); assert (sym != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FINI, sym->st_value); } // XXX Support init,fini,preinit arrays /* The hash table which comes with dynamic symbol table. */ xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.hashscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_HASH, shdr->sh_addr); /* Reference to the symbol table section. */ assert (ld_state.dynsymscnidx != 0); xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynsymscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMTAB, shdr->sh_addr); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMENT, xelf_fsize (ld_state.outelf, ELF_T_SYM, 1)); /* And the string table which comes with it. */ xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynstrscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRTAB, shdr->sh_addr); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRSZ, shdr->sh_size); /* Add the entries related to the .plt. */ if (ld_state.nplt > 0) { // XXX Make this work if there is no PLT xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.gotpltscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, // XXX This should probably be machine // dependent. DT_PLTGOT, shdr->sh_addr); xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.pltrelscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_PLTRELSZ, shdr->sh_size); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_JMPREL, shdr->sh_addr); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_PLTREL, REL_TYPE (statep)); } if (ld_state.relsize_total > 0) { int rel = REL_TYPE (statep); xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.reldynscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, rel, shdr->sh_addr); /* Trick ahead. Use arithmetic to get the right tag. We check the validity of this assumption in the asserts. */ assert (DT_RELASZ - DT_RELA == 1); assert (DT_RELSZ - DT_REL == 1); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, rel + 1, shdr->sh_size); /* Similar for the entry size tag. */ assert (DT_RELAENT - DT_RELA == 2); assert (DT_RELENT - DT_REL == 2); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, rel + 2, rel == DT_REL ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1) : xelf_fsize (ld_state.outelf, ELF_T_RELA, 1)); } if (ld_state.verneedscnidx != 0) { xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.verneedscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_VERNEED, shdr->sh_addr); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_VERNEEDNUM, ld_state.nverdeffile); } if (ld_state.versymscnidx != 0) { xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.versymscnidx), shdr); assert (shdr != NULL); new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_VERSYM, shdr->sh_addr); } /* We always create the DT_DEBUG entry. */ new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_DEBUG, 0); assert (ld_state.ndynamic_filled < ld_state.ndynamic); /* Add the flag words if necessary. */ if (ld_state.dt_flags != 0) new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FLAGS, ld_state.dt_flags); /* Create entry for the DT_FLAGS_1 flag. */ if (ld_state.dt_flags_1 != 0) new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FLAGS_1, ld_state.dt_flags_1); /* Create entry for the DT_FEATURE_1 flag. */ if (ld_state.dt_feature_1 != 0) new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FEATURE_1, ld_state.dt_feature_1); assert (ld_state.ndynamic_filled <= ld_state.ndynamic); } } // XXX The following code isn't nice. We use two different // mechanisms to handle relocations, one for relocatable files, one // for executables and DSOs. Maybe this is the best method but also // maybe it can be somewhat unified. /* Now that we created the symbol table we can add the reference to it in the sh_link field of the section headers of the relocation sections. */ while (rellist != NULL) { assert (ld_state.file_type == relocatable_file_type); Elf_Scn *outscn; outscn = elf_getscn (ld_state.outelf, rellist->scnidx); xelf_getshdr (outscn, shdr); /* This must not fail since we did it before. */ assert (shdr != NULL); /* Remember the symbol table which belongs to the relocation section. */ shdr->sh_link = ld_state.symscnidx; /* And the reference to the section which is relocated by this relocation section. We use the info from the first input section but all records should have the same information. */ shdr->sh_info = rellist->scninfo->fileinfo->scninfo[SCNINFO_SHDR (rellist->scninfo->shdr).sh_info].outscnndx; /* Perform the actual relocations. We only have to adjust offsets and symbol indices. */ RELOCATE_SECTION (statep, outscn, rellist->scninfo, dblindirect); /* Store the changes. */ (void) xelf_update_shdr (outscn, shdr); /* Up to the next relocation section. */ rellist = rellist->next; } if (ld_state.rellist != NULL) { assert (ld_state.file_type != relocatable_file_type); /* Create the relocations for the output file. */ CREATE_RELOCATIONS (statep, dblindirect); } /* We need the ELF header once more. */ xelf_getehdr (ld_state.outelf, ehdr); assert (ehdr != NULL); /* Set the section header string table index. */ if (likely (shstrtab_ndx < SHN_HIRESERVE) && likely (shstrtab_ndx != SHN_XINDEX)) ehdr->e_shstrndx = shstrtab_ndx; else { /* We have to put the section index in the sh_link field of the zeroth section header. */ Elf_Scn *scn = elf_getscn (ld_state.outelf, 0); xelf_getshdr (scn, shdr); if (unlikely (shdr == NULL)) error (EXIT_FAILURE, 0, gettext ("cannot get header of 0th section: %s"), elf_errmsg (-1)); shdr->sh_link = shstrtab_ndx; (void) xelf_update_shdr (scn, shdr); ehdr->e_shstrndx = SHN_XINDEX; } if (ld_state.file_type != relocatable_file_type) /* DSOs and executables have to define the entry point symbol. */ ehdr->e_entry = find_entry_point (); if (unlikely (xelf_update_ehdr (ld_state.outelf, ehdr) == 0)) error (EXIT_FAILURE, 0, gettext ("cannot update ELF header: %s"), elf_errmsg (-1)); /* Free the data which we don't need anymore. */ free (ld_state.dblindirect); /* Finalize the .plt section and what else belongs to it. */ FINALIZE_PLT (statep, nsym, nsym_local, ndxtosym); /* Finally, if we have to compute the build ID. */ if (ld_state.build_id != NULL) compute_build_id (); /* We don't need the map from the symbol table index to the symbol structure anymore. */ free (ndxtosym); return 0; } /* This is a function which must be specified in all backends. */ static void ld_generic_relocate_section (struct ld_state *statep, Elf_Scn *outscn, struct scninfo *firstp, const Elf32_Word *dblindirect) { error (EXIT_FAILURE, 0, gettext ("\ linker backend didn't specify function to relocate section")); /* NOTREACHED */ } /* Finalize the output file. */ static int ld_generic_finalize (struct ld_state *statep) { /* Write out the ELF file data. */ if (elf_update (ld_state.outelf, ELF_C_WRITE) == -1) error (EXIT_FAILURE, 0, gettext ("while writing output file: %s"), elf_errmsg (-1)); /* Free the resources. */ if (elf_end (ld_state.outelf) != 0) error (EXIT_FAILURE, 0, gettext ("while finishing output file: %s"), elf_errmsg (-1)); /* Get the file status of the temporary file. */ struct stat temp_st; if (fstat (ld_state.outfd, &temp_st) != 0) error (EXIT_FAILURE, errno, gettext ("cannot stat output file")); /* Now it's time to rename the file. Remove an old existing file first. */ if (rename (ld_state.tempfname, ld_state.outfname) != 0) /* Something went wrong. */ error (EXIT_FAILURE, errno, gettext ("cannot rename output file")); /* Make sure the output file is really the one we created. */ struct stat new_st; if (stat (ld_state.outfname, &new_st) != 0 || new_st.st_ino != temp_st.st_ino || new_st.st_dev != temp_st.st_dev) { /* Wow, somebody overwrote the output file, probably some intruder. */ unlink (ld_state.outfname); error (EXIT_FAILURE, 0, gettext ("\ WARNING: temporary output file overwritten before linking finished")); } /* Close the file descriptor. */ (void) close (ld_state.outfd); /* Signal the cleanup handler that the file is correctly created. */ ld_state.tempfname = NULL; return 0; } static bool ld_generic_special_section_number_p (struct ld_state *statep, size_t number) { /* There are no special section numbers in the gABI. */ return false; } static bool ld_generic_section_type_p (struct ld_state *statep, GElf_Word type) { if (type < SHT_NUM /* XXX Enable the following two when implemented. */ // || type == SHT_GNU_LIBLIST // || type == SHT_CHECKSUM /* XXX Eventually include SHT_SUNW_move, SHT_SUNW_COMDAT, and SHT_SUNW_syminfo. */ || (type >= SHT_GNU_verdef && type <= SHT_GNU_versym)) return true; return false; } static XElf_Xword ld_generic_dynamic_section_flags (struct ld_state *statep) { /* By default the .dynamic section is writable (and is of course loaded). Few architecture differ from this. */ return SHF_ALLOC | SHF_WRITE; } static void ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "initialize_plt"); } static void ld_generic_initialize_pltrel (struct ld_state *statep, Elf_Scn *scn) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "initialize_pltrel"); } static void ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "initialize_got"); } static void ld_generic_initialize_gotplt (struct ld_state *statep, Elf_Scn *scn) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "initialize_gotplt"); } static void ld_generic_finalize_plt (struct ld_state *statep, size_t nsym, size_t nsym_dyn, struct symbol **ndxtosymp) { /* By default we assume that nothing has to be done. */ } static int ld_generic_rel_type (struct ld_state *statep) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "rel_type"); /* Just to keep the compiler calm. */ return 0; } static void ld_generic_count_relocations (struct ld_state *statep, struct scninfo *scninfo) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "count_relocations"); } static void ld_generic_create_relocations (struct ld_state *statep, const Elf32_Word *dblindirect) { /* This cannot be implemented generally. There should have been a machine dependent implementation and we should never have arrived here. */ error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"), "create_relocations"); }