C++程序  |  1074行  |  30.66 KB

/* Copyright (C) 2001, 2002, 2003 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;
};


/* 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, int symidx);
extern inline bool
linked_from_dso_p (struct scninfo *scninfo, int 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 */