diff options
Diffstat (limited to 'src/ld.h')
-rw-r--r-- | src/ld.h | 1074 |
1 files changed, 1074 insertions, 0 deletions
diff --git a/src/ld.h b/src/ld.h new file mode 100644 index 00000000..a463a188 --- /dev/null +++ b/src/ld.h @@ -0,0 +1,1074 @@ +/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc. + Written by Ulrich Drepper <drepper@redhat.com>, 2001. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifndef LD_H +#define LD_H 1 + +#include <dlfcn.h> +#include <obstack.h> +#include <stdbool.h> +#include <stdio.h> +#include "xelf.h" + + +/* Recommended size of the buffer passed to ld_strerror. */ +#define ERRBUFSIZE (512) + +/* Character used to introduce version name after symbol. */ +#define VER_CHR '@' + + +/* Methods for handling archives. */ +enum extract_rule + { + defaultextract, /* Weak references don't cause archive member to + be used. */ + weakextract, /* Weak references cause archive member to be + extracted. */ + allextract /* Extract all archive members regardless of + references (aka whole-archive). */ + }; + + +/* Type of output file. */ +enum file_type + { + no_file_type = 0, /* None selected so far. */ + executable_file_type, /* Executable. */ + dso_file_type, /* DSO. */ + dso_needed_file_type, /* DSO introduced by DT_NEEDED. */ + relocatable_file_type, /* Relocatable object file. */ + archive_file_type /* Archive (input only). */ + }; + + +struct usedfiles +{ + /* The next file given at the command line. */ + struct usedfiles *next; + /* Nonzero if this file is the beginning of a group. */ + bool group_start; + /* Nonzero if this file is the end of a group. */ + bool group_end; + /* Pointer to the beginning of the group. It is necessary to + explain why we cannot simply use the 'next' pointer and have a + circular single-linked list like in many cases. The problem is + that the last archive of the group, if it is the last file of the + group, contains the only existing pointer to the next file we + have to look at. All files are initially connected via the + 'next' pointer in a single-linked list. Therefore we cannot + overwrite this value. It instead will be used once the group is + handled and we go on processing the rest of the files. */ + struct usedfiles *group_backref; + + /* Name/path of the file. */ + const char *fname; + /* Resolved file name. */ + const char *rfname; + /* Name used as reference in DT_NEEDED entries. This is normally + the SONAME. If it is missing it's normally the fname above. */ + const char *soname; + /* Handle for the SONAME in the string table. */ + struct Ebl_Strent *sonameent; + + /* Help to identify duplicates. */ + dev_t dev; + ino_t ino; + + enum + { + not_opened, + opened, + in_archive, + closed + } status; + + /* How to extract elements from archives. */ + enum extract_rule extract_rule; + + /* Lazy-loading rule. */ + bool lazyload; + + /* If this is a DSO the flag indicates whether the file is directly + used in a reference. */ + bool used; + + /* If nonzero this is the archive sequence number which can be used to + determine whether back refernces from -( -) or GROUP statements + have to be followed. */ + int archive_seq; + + /* Pointer to the record for the archive containing this file. */ + struct usedfiles *archive_file; + + /* Type of file. We have to distinguish these types since they + are searched for differently. */ + enum file_type file_type; + /* This is the ELF library handle for this file. */ + Elf *elf; + + /* The ELF header. */ +#if NATIVE_ELF != 0 + XElf_Ehdr *ehdr; +# define FILEINFO_EHDR(fi) (*(fi)) +#else + XElf_Ehdr ehdr; +# define FILEINFO_EHDR(fi) (fi) +#endif + + /* Index of the section header string table section. We use a + separate field and not the e_shstrndx field in the ELF header + since in case of a file with more than 64000 sections the index + might be stored in the section header of section zero. The + elf_getshstrndx() function can find the value but it is too + costly to repeat this call over and over. */ + size_t shstrndx; + + /* Info about the sections of the file. */ + struct scninfo + { + /* Handle for the section. Note that we can store a section + handle here because the file is not changing. This together + with the knowledge about the libelf library is enough for us to + assume the section reference remains valid at all times. */ + Elf_Scn *scn; + /* Section header. */ +#if NATIVE_ELF != 0 + XElf_Shdr *shdr; +# define SCNINFO_SHDR(si) (*(si)) +#else + XElf_Shdr shdr; +# define SCNINFO_SHDR(si) (si) +#endif + /* Offset of this files section in the combined section. */ + XElf_Off offset; + /* Index of the section in the output file. */ + Elf32_Word outscnndx; + /* Index of the output section in the 'allsection' array. */ + Elf32_Word allsectionsidx; + /* True if the section is used. */ + bool used; + /* Section group number. This is the index of the SHT_GROUP section. */ + Elf32_Word grpid; + /* Pointer back to the containing file information structure. */ + struct usedfiles *fileinfo; + /* List of symbols in this section (set only for merge-able sections). */ + struct symbol *symbols; + /* Size of relocations in this section. Only used for relocation + sections. */ + size_t relsize; + /* Pointer to next section which is put in the given output + section. */ + struct scninfo *next; + } *scninfo; + + /* List of section group sections. */ + struct scninfo *groups; + + /* The symbol table section. + + XXX Maybe support for more than one symbol table is needed. */ + Elf_Data *symtabdata; + /* Extra section index table section. */ + Elf_Data *xndxdata; + /* Dynamic symbol table section. */ + Elf_Data *dynsymtabdata; + /* The version number section. */ + Elf_Data *versymdata; + /* The defined versions. */ + Elf_Data *verdefdata; + /* Number of versions defined. */ + size_t nverdef; + /* True if the version with the given index number is used in the + output. */ + XElf_Versym *verdefused; + /* How many versions are used. */ + size_t nverdefused; + /* Handle for name of the version. */ + struct Ebl_Strent **verdefent; + /* The needed versions. */ + Elf_Data *verneeddata; + /* String table section associated with the symbol table. */ + Elf32_Word symstridx; + /* String table section associated with the dynamic symbol table. */ + Elf32_Word dynsymstridx; + /* Number of entries in the symbol table. */ + size_t nsymtab; + size_t nlocalsymbols; + size_t ndynsymtab; + /* Dynamic section. */ + Elf_Scn *dynscn; + + /* Indirection table for the symbols defined here. */ + Elf32_Word *symindirect; + Elf32_Word *dynsymindirect; + /* For undefined or common symbols we need a reference to the symbol + record. */ + struct symbol **symref; + struct symbol **dynsymref; + + /* This is the file descriptor. The value is -1 if the descriptor + was already closed. This can happen if we needed file descriptors + to open new files. */ + int fd; + /* This flag is true if the descriptor was passed to the generic + functions from somewhere else. This is an implementation detail; + no machine-specific code must use this flag. */ + bool fd_passed; + + /* True if any of the sections is merge-able. */ + bool has_merge_sections; +}; + + +/* Functions to test for the various types of files we handle. */ +static inline int +ld_file_rel_p (struct usedfiles *file) +{ + return (elf_kind (file->elf) == ELF_K_ELF + && FILEINFO_EHDR (file->ehdr).e_type == ET_REL); +} + +static inline int +ld_file_dso_p (struct usedfiles *file) +{ + return (elf_kind (file->elf) == ELF_K_ELF + && FILEINFO_EHDR (file->ehdr).e_type == ET_DYN); +} + +static inline int +ld_file_ar_p (struct usedfiles *file) +{ + return elf_kind (file->elf) == ELF_K_AR; +} + + +struct pathelement +{ + /* The next path to search. */ + struct pathelement *next; + /* The path name. */ + const char *pname; + /* Larger than zero if the directory exists, smaller than zero if not, + zero if it is not yet known. */ + int exist; +}; + + +/* Forward declaration. */ +struct ld_state; + + +/* Callback functions. */ +struct callbacks +{ + /* Library names passed to the linker as -lXXX represent files named + libXXX.YY. The YY part can have different forms, depending on the + architecture. The generic set is .so and .a (in this order). */ + const char **(*lib_extensions) (struct ld_state *) + __attribute__ ((__const__)); +#define LIB_EXTENSION(state) \ + DL_CALL_FCT ((state)->callbacks.lib_extensions, (state)) + + /* Process the given file. If the file is not yet open, open it. + 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.*/ + int (*file_process) (int fd, struct usedfiles *, struct ld_state *, + struct usedfiles **); +#define FILE_PROCESS(fd, file, state, nextp) \ + DL_CALL_FCT ((state)->callbacks.file_process, (fd, file, state, nextp)) + + /* Close the given file. */ + int (*file_close) (struct usedfiles *, struct ld_state *); +#define FILE_CLOSE(file, state) \ + DL_CALL_FCT ((state)->callbacks.file_close, (file, state)) + + /* Create the output sections now. This requires knowledge about + all the sections we will need. It may be necessary to sort the + 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. */ + void (*create_sections) (struct ld_state *); +#define CREATE_SECTIONS(state) \ + DL_CALL_FCT ((state)->callbacks.create_sections, (state)) + + /* Determine whether we have any non-weak unresolved references left. */ + int (*flag_unresolved) (struct ld_state *); +#define FLAG_UNRESOLVED(state) \ + DL_CALL_FCT ((state)->callbacks.flag_unresolved, (state)) + + /* Create the sections which are generated by the linker and are not + present in the input file. */ + void (*generate_sections) (struct ld_state *); +#define GENERATE_SECTIONS(state) \ + DL_CALL_FCT ((state)->callbacks.generate_sections, (state)) + + /* Open the output file. The file name is given or "a.out". We + create as much of the ELF structure as possible. */ + int (*open_outfile) (struct ld_state *, int, int, int); +#define OPEN_OUTFILE(state, machine, class, data) \ + DL_CALL_FCT ((state)->callbacks.open_outfile, (state, machine, class, data)) + + /* Create the data for the output file. */ + int (*create_outfile) (struct ld_state *); +#define CREATE_OUTFILE(state) \ + DL_CALL_FCT ((state)->callbacks.create_outfile, (state)) + + /* Process a relocation section. */ + void (*relocate_section) (struct ld_state *, Elf_Scn *, struct scninfo *, + const Elf32_Word *); +#define RELOCATE_SECTION(state, outscn, first, dblindirect) \ + DL_CALL_FCT ((state)->callbacks.relocate_section, (state, outscn, first, \ + dblindirect)) + + /* Allocate a data buffer for the relocations of the given output + section. */ + void (*count_relocations) (struct ld_state *, struct scninfo *); +#define COUNT_RELOCATIONS(state, scninfo) \ + DL_CALL_FCT ((state)->callbacks.count_relocations, (state, scninfo)) + + /* Create relocations for executable or DSO. */ + void (*create_relocations) (struct ld_state *, const Elf32_Word *); +#define CREATE_RELOCATIONS(state, dlbindirect) \ + DL_CALL_FCT ((state)->callbacks.create_relocations, (state, dblindirect)) + + /* Finalize the output file. */ + int (*finalize) (struct ld_state *); +#define FINALIZE(state) \ + DL_CALL_FCT ((state)->callbacks.finalize, (state)) + + /* Check whether special section number is known. */ + bool (*special_section_number_p) (struct ld_state *, size_t); +#define SPECIAL_SECTION_NUMBER_P(state, number) \ + DL_CALL_FCT ((state)->callbacks.special_section_number_p, (state, number)) + + /* Check whether section type is known. */ + bool (*section_type_p) (struct ld_state *, XElf_Word); +#define SECTION_TYPE_P(state, type) \ + DL_CALL_FCT ((state)->callbacks.section_type_p, (state, type)) + + /* Return section flags for .dynamic section. */ + XElf_Xword (*dynamic_section_flags) (struct ld_state *); +#define DYNAMIC_SECTION_FLAGS(state) \ + DL_CALL_FCT ((state)->callbacks.dynamic_section_flags, (state)) + + /* Create the data structures for the .plt section and initialize it. */ + void (*initialize_plt) (struct ld_state *, Elf_Scn *scn); +#define INITIALIZE_PLT(state, scn) \ + DL_CALL_FCT ((state)->callbacks.initialize_plt, (state, scn)) + + /* Create the data structures for the .rel.plt section and initialize it. */ + void (*initialize_pltrel) (struct ld_state *, Elf_Scn *scn); +#define INITIALIZE_PLTREL(state, scn) \ + DL_CALL_FCT ((state)->callbacks.initialize_pltrel, (state, scn)) + + /* Finalize the .plt section the what belongs to them. */ + void (*finalize_plt) (struct ld_state *, size_t, size_t); +#define FINALIZE_PLT(state, nsym, nsym_dyn) \ + DL_CALL_FCT ((state)->callbacks.finalize_plt, (state, nsym, nsym_dyn)) + + /* Create the data structures for the .got section and initialize it. */ + void (*initialize_got) (struct ld_state *, Elf_Scn *scn); +#define INITIALIZE_GOT(state, scn) \ + DL_CALL_FCT ((state)->callbacks.initialize_got, (state, scn)) + + /* Return the tag corresponding to the native relocation type for + the platform. */ + int (*rel_type) (struct ld_state *); +#define REL_TYPE(state) \ + DL_CALL_FCT ((state)->callbacks.rel_type, (state)) +}; + + +/* Structure for symbol representation. This data structure is used a + lot, so size is important. */ +struct symbol +{ + /* Symbol name. */ + const char *name; + /* Size of the object. */ + XElf_Xword size; + /* Index of the symbol in the symbol table of the object. */ + size_t symidx; + /* Index of the symbol in the symbol table of the output file. */ + size_t outsymidx; + + /* Description where the symbol is found/needed. */ + size_t scndx; + struct usedfiles *file; + /* Index of the symbol table. */ + Elf32_Word symscndx; + + /* Index of the symbol in the dynamic symbol table of the output + file. Note that the value only needs to be 16 bit wide since + there cannot be more sections in an executable or DSO. */ + unsigned int outdynsymidx:16; + + /* Type of the symbol. */ + unsigned int type:4; + /* Various flags. */ + unsigned int defined:1; + unsigned int common:1; + unsigned int weak:1; + unsigned int added:1; + unsigned int merged:1; + /* Nonzero if the symbol is on the from_dso list. */ + unsigned int on_dsolist:1; + /* Nonzero if symbol needs copy relocation, reset when the + relocation has been created. */ + unsigned int need_copy:1; + unsigned int in_dso:1; + + union + { + /* Pointer to the handle created by the functions which create + merged section contents. We use 'void *' because there are + different implementations used. */ + void *handle; + XElf_Addr value; + } merge; + + /* Pointer to next/previous symbol on whatever list the symbol is. */ + struct symbol *next; + struct symbol *previous; + /* Pointer to next symbol of the same section (only set for merge-able + sections). */ + struct symbol *next_in_scn; +}; + + +/* Get the definition for the symbol table. */ +#include <symbolhash.h> + +/* Simple single linked list of file names. */ +struct filename_list +{ + const char *name; + struct usedfiles *real; + struct filename_list *next; + bool group_start; + bool group_end; + bool as_needed; +}; + + +/* Data structure to describe expression in linker script. */ +struct expression +{ + enum expression_tag + { + exp_num, + exp_sizeof_headers, + exp_pagesize, + exp_id, + exp_mult, + exp_div, + exp_mod, + exp_plus, + exp_minus, + exp_and, + exp_or, + exp_align + } tag; + + union + { + uintmax_t num; + struct expression *child; + struct + { + struct expression *left; + struct expression *right; + } binary; + const char *str; + } val; +}; + + +/* Data structure for section name with flags. */ +struct input_section_name +{ + const char *name; + bool sort_flag; +}; + +/* File name mask with section name. */ +struct filemask_section_name +{ + const char *filemask; + const char *excludemask; + struct input_section_name *section_name; + bool keep_flag; +}; + +/* Data structure for assignments. */ +struct assignment +{ + const char *variable; + struct expression *expression; + struct symbol *sym; + bool provide_flag; +}; + + +/* Data structure describing input for an output section. */ +struct input_rule +{ + enum + { + input_section, + input_assignment + } tag; + + union + { + struct assignment *assignment; + struct filemask_section_name *section; + } val; + + struct input_rule *next; +}; + + +/* Data structure to describe output section. */ +struct output_section +{ + const char *name; + struct input_rule *input; + XElf_Addr max_alignment; + bool ignored; +}; + + +/* Data structure to describe output file format. */ +struct output_rule +{ + enum + { + output_section, + output_assignment + } tag; + + union + { + struct assignment *assignment; + struct output_section section; + } val; + + struct output_rule *next; +}; + + +/* List of all the segments the linker script describes. */ +struct output_segment +{ + int mode; + struct output_rule *output_rules; + struct output_segment *next; + + XElf_Off offset; + XElf_Addr addr; + XElf_Xword align; +}; + + +/* List of identifiers. */ +struct id_list +{ + union + { + enum id_type + { + id_str, /* Normal string. */ + id_all, /* "*", matches all. */ + id_wild /* Globbing wildcard string. */ + } id_type; + struct + { + bool local; + const char *versionname; + } s; + } u; + const char *id; + struct id_list *next; +}; + + +/* Version information. */ +struct version +{ + struct version *next; + struct id_list *local_names; + struct id_list *global_names; + const char *versionname; + const char *parentname; +}; + + +/* Head for list of sections. */ +struct scnhead +{ + /* Name of the sections. */ + const char *name; + + /* Accumulated flags for the sections. */ + XElf_Xword flags; + + /* Type of the sections. */ + XElf_Word type; + + /* Entry size. If there are differencs between the sections with + the same name this field contains 1. */ + XElf_Word entsize; + + /* If non-NULL pointer to group signature. */ + const char *grp_signature; + + /* Maximum alignment for all sections. */ + XElf_Word align; + + /* Distinguish between normal sections coming from the input file + and sections generated by the linker. */ + enum scn_kind + { + scn_normal, /* Section from the input file(s). */ + scn_dot_interp, /* Generated .interp section. */ + scn_dot_got, /* Generated .got section. */ + scn_dot_dynrel, /* Generated .rel.dyn section. */ + scn_dot_dynamic, /* Generated .dynamic section. */ + scn_dot_dynsym, /* Generated .dynsym section. */ + scn_dot_dynstr, /* Generated .dynstr section. */ + scn_dot_hash, /* Generated .hash section. */ + scn_dot_plt, /* Generated .plt section. */ + scn_dot_pltrel, /* Generated .rel.plt section. */ + scn_dot_version, /* Generated .gnu.version section. */ + scn_dot_version_r /* Generated .gnu.version_r section. */ + } kind; + + /* True is the section is used in the output. */ + bool used; + + /* Total size (only determined this way for relocation sections). */ + size_t relsize; + + /* Filled in by the section sorting to indicate which segment the + section goes in. */ + int segment_nr; + + /* Index of the output section. We cannot store the section handle + directly here since the handle is a pointer in a dynamically + allocated table which might move if it becomes too small for all + the sections. Using the index the correct value can be found at + all times. */ + XElf_Word scnidx; + + /* Index of the STT_SECTION entry for this section in the symbol + table. */ + XElf_Word scnsymidx; + + /* Address of the section in the output file. */ + XElf_Addr addr; + + /* Handle for the section name in the output file's section header + string table. */ + struct Ebl_Strent *nameent; + + /* Tail of list of symbols for this section. Only set if the + section is merge-able. */ + struct symbol *symbols; + + /* Pointer to last section. */ + struct scninfo *last; +}; + + +/* Define hash table for sections. */ +#include <sectionhash.h> + +/* Define hash table for version symbols. */ +#include <versionhash.h> + + +/* State of the linker. */ +struct ld_state +{ + /* ELF backend library handle. */ + Ebl *ebl; + + /* List of all archives participating, in this order. */ + struct usedfiles *archives; + /* End of the list. */ + struct usedfiles *tailarchives; + /* If nonzero we are looking for the beginning of a group. */ + bool group_start_requested; + /* Pointer to the archive starting the group. */ + struct usedfiles *group_start_archive; + + /* List of the DSOs we found. */ + struct usedfiles *dsofiles; + /* Number of DSO files. */ + size_t ndsofiles; + /* Ultimate list of object files which are linked in. */ + struct usedfiles *relfiles; + + /* List the DT_NEEDED DSOs. */ + struct usedfiles *needed; + + /* Temporary storage for the parser. */ + struct filename_list *srcfiles; + + /* List of all the paths to look at. */ + struct pathelement *paths; + /* Tail of the list. */ + struct pathelement *tailpaths; + + /* User provided paths for lookup of DSOs. */ + struct pathelement *rpath; + struct pathelement *rpath_link; + struct pathelement *runpath; + struct pathelement *runpath_link; + struct Ebl_Strent *rxxpath_strent; + int rxxpath_tag; + + /* From the environment variable LD_LIBRARY_PATH. */ + struct pathelement *ld_library_path1; + struct pathelement *ld_library_path2; + + /* Name of the output file. */ + const char *outfname; + /* Name of the temporary file we initially create. */ + const char *tempfname; + /* File descriptor opened for the output file. */ + int outfd; + /* The ELF descriptor for the output file. */ + Elf *outelf; + + /* Type of output file. */ + enum file_type file_type; + + /* Is this a system library or not. */ + bool is_system_library; + + /* Page size to be assumed for the binary. */ + size_t pagesize; + + /* Name of the interpreter for dynamically linked objects. */ + const char *interp; + /* Index of the .interp section. */ + Elf32_Word interpscnidx; + + /* Optimization level. */ + unsigned long int optlevel; + + /* If true static linking is requested. */ + bool statically; + + /* How to extract elements from archives. */ + enum extract_rule extract_rule; + + /* Sequence number of the last archive we used. */ + int last_archive_used; + + /* If true print to stdout information about the files we are + trying to open. */ + bool trace_files; + + /* If true multiple definitions are not considered an error; the + first is used. */ + bool muldefs; + + /* If true undefined symbols when building DSOs are not fatal. */ + bool nodefs; + + /* If true add line indentifying link-editor to .comment section. */ + bool add_ld_comment; + + /* Stripping while linking. */ + enum + { + strip_none, + strip_debug, + strip_all, + strip_everything + } strip; + + /* The callback function vector. */ + struct callbacks callbacks; + + /* Name of the entry symbol. Can also be a numeric value. */ + const char *entry; + + /* The description of the segments in the output file. */ + struct output_segment *output_segments; + + /* List of the symbols we created from linker script definitions. */ + struct symbol *lscript_syms; + size_t nlscript_syms; + + /* Table with known symbols. */ + ld_symbol_tab symbol_tab; + + /* Table with used sections. */ + ld_section_tab section_tab; + + /* The list of sections once we collected them. */ + struct scnhead **allsections; + size_t nallsections; + size_t nusedsections; + size_t nnotesections; + + /* Beginning of the list of symbols which are still unresolved. */ + struct symbol *unresolved; + /* Number of truely unresolved entries in the list. */ + size_t nunresolved; + /* Number of truely unresolved, non-weak entries in the list. */ + size_t nunresolved_nonweak; + + /* List of common symbols. */ + struct symbol *common_syms; + /* Section for the common symbols. */ + struct scninfo *common_section; + + /* List of symbols defined in DSOs and used in a relocatable file. + DSO symbols not referenced in the relocatable files are not on + the list. If a symbol is on the list the on_dsolist field in the + 'struct symbol' is nonzero. */ + struct symbol *from_dso; + /* Number of entries in from_dso. */ + size_t nfrom_dso; + /* Number of entries in the dynamic symbol table. */ + size_t ndynsym; + /* Number of PLT entries from DSO references. */ + size_t nplt; + /* Number of PLT entries from DSO references. */ + size_t ngot; + /* Number of copy relocations. */ + size_t ncopy; + /* Section for copy relocations. */ + struct scninfo *copy_section; + + /* Keeping track of the number of symbols in the output file. */ + size_t nsymtab; + size_t nlocalsymbols; + + /* Special symbols. */ + struct symbol *init_symbol; + struct symbol *fini_symbol; + + /* The description of the segments in the output file as described + in the default linker script. This information will be used in + addition to the user-provided information. */ + struct output_segment *default_output_segments; + /* Search paths added by the default linker script. */ + struct pathelement *default_paths; + +#ifndef BASE_ELF_NAME + /* The handle of the ld backend library. */ + void *ldlib; +#endif + + /* String table for the section headers. */ + struct Ebl_Strtab *shstrtab; + + /* True if output file should contain symbol table. */ + bool need_symtab; + /* Symbol table section. */ + Elf32_Word symscnidx; + /* Extended section table section. */ + Elf32_Word xndxscnidx; + /* Symbol string table section. */ + Elf32_Word strscnidx; + + /* True if output file should contain dynamic symbol table. */ + bool need_dynsym; + /* Dynamic symbol table section. */ + Elf32_Word dynsymscnidx; + /* Dynamic symbol string table section. */ + Elf32_Word dynstrscnidx; + /* Dynamic symbol hash table. */ + size_t hashscnidx; + + /* Procedure linkage table section. */ + Elf32_Word pltscnidx; + /* Number of entries already in the PLT section. */ + size_t nplt_used; + /* Relocation for procedure linkage table section. */ + Elf32_Word pltrelscnidx; + + /* Global offset table section. */ + Elf32_Word gotscnidx; + + /* This section will hole all non-PLT relocations. */ + Elf32_Word reldynscnidx; + + /* Index of the sections to handle versioning. */ + Elf32_Word versymscnidx; + Elf32_Word verneedscnidx; + /* XXX Should the following names be verneed...? */ + /* Number of version definitions in input DSOs used. */ + int nverdefused; + /* Number of input DSOs using versioning. */ + int nverdeffile; + /* Index of next version. */ + int nextveridx; + + /* Hash table for version symbol strings. Only strings without + special characters are hashed here. */ + ld_version_str_tab version_str_tab; + /* At most one of the following two variables is set to true if either + global or local symbol binding is selected as the default. */ + bool default_bind_local; + bool default_bind_global; + + /* True if only used sections are used. */ + bool gc_sections; + + /* Array to determine final index of symbol. */ + Elf32_Word *dblindirect; + + /* Section group handling. */ + struct scngroup + { + Elf32_Word outscnidx; + int nscns; + struct member + { + struct scnhead *scn; + struct member *next; + } *member; + struct Ebl_Strent *nameent; + struct symbol *symbol; + struct scngroup *next; + } *groups; + + /* True if the output file needs a .got section. */ + bool need_got; + /* Number of relocations for GOT section caused. */ + size_t nrel_got; + + /* Number of entries needed in the .dynamic section. */ + int ndynamic; + /* To keep track of added entries. */ + int ndynamic_filled; + /* Index for the dynamic section. */ + Elf32_Word dynamicscnidx; + + /* Flags set in the DT_FLAGS word. */ + Elf32_Word dt_flags; + /* Flags set in the DT_FLAGS_1 word. */ + Elf32_Word dt_flags_1; + /* Flags set in the DT_FEATURE_1 word. */ + Elf32_Word dt_feature_1; + + /* Lazy-loading state for dependencies. */ + bool lazyload; + + /* True is DSOs which are not used in the linking process are not + recorded. */ + bool ignore_unused_dsos; + + + /* True if in executables all global symbols should be exported in + the dynamic symbol table. */ + bool export_all_dynamic; + + /* If DSO is generated, this is the SONAME. */ + const char *soname; + + /* List of all relocation sections. */ + struct scninfo *rellist; + /* Total size of non-PLT relocations. */ + size_t relsize_total; + + /* Record for the GOT symbol, if known. */ + struct symbol *got_symbol; + /* Record for the dynamic section symbol, if known. */ + struct symbol *dyn_symbol; + + /* Obstack used for small objects which will not be deleted. */ + struct obstack smem; +}; + + +/* The interface to the scanner. */ + +/* Parser entry point. */ +extern int ldparse (void); + +/* The input file. */ +extern FILE *ldin; + +/* Name of the input file. */ +extern const char *ldin_fname; + +/* Current line number. Must be reset for a new file. */ +extern int ldlineno; + +/* If nonzero we are currently parsing a version script. */ +extern int ld_scan_version_script; + +/* Flags defined in ld.c. */ +extern int verbose; +extern int conserve_memory; + + +/* Linker state. This contains all global information. */ +extern struct ld_state ld_state; + + +/* Generic ld helper functions. */ + +/* Append a new directory to search libraries in. */ +extern void ld_new_searchdir (const char *dir); + +/* Append a new file to the list of input files. */ +extern struct usedfiles *ld_new_inputfile (const char *fname, + enum file_type type); + + +/* These are the generic implementations for the callbacks used by ld. */ + +/* Initialize state object. This callback function is called after the + parameters are parsed but before any file is searched for. */ +extern int ld_prepare_state (const char *emulation); + + +/* Function to determine whether an object will be dynamically linked. */ +extern bool dynamically_linked_p (void); + +/* Helper functions for the architecture specific code. */ + +/* Checked whether the symbol is undefined and referenced from a DSO. */ +extern bool linked_from_dso_p (struct scninfo *scninfo, size_t symidx); +extern inline 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; +} + +#endif /* ld.h */ |