More dynamic object support, initial scripting support.
This commit is contained in:
parent
6c73cbb1d9
commit
dbe717effb
31 changed files with 3698 additions and 373 deletions
326
elfcpp/elfcpp.h
326
elfcpp/elfcpp.h
|
@ -530,6 +530,138 @@ elf_r_info<64>(unsigned int s, unsigned int t)
|
|||
return (static_cast<Elf_Xword>(s) << 32) + (t & 0xffffffff);
|
||||
}
|
||||
|
||||
// Dynamic tags found in the PT_DYNAMIC segment.
|
||||
|
||||
enum DT
|
||||
{
|
||||
DT_NULL = 0,
|
||||
DT_NEEDED = 1,
|
||||
DT_PLTRELSZ = 2,
|
||||
DT_PLTGOT = 3,
|
||||
DT_HASH = 4,
|
||||
DT_STRTAB = 5,
|
||||
DT_SYMTAB = 6,
|
||||
DT_RELA = 7,
|
||||
DT_RELASZ = 8,
|
||||
DT_RELAENT = 9,
|
||||
DT_STRSZ = 10,
|
||||
DT_SYMENT = 11,
|
||||
DT_INIT = 12,
|
||||
DT_FINI = 13,
|
||||
DT_SONAME = 14,
|
||||
DT_RPATH = 15,
|
||||
DT_SYMBOLIC = 16,
|
||||
DT_REL = 17,
|
||||
DT_RELSZ = 18,
|
||||
DT_RELENT = 19,
|
||||
DT_PLTREL = 20,
|
||||
DT_DEBUG = 21,
|
||||
DT_TEXTREL = 22,
|
||||
DT_JMPREL = 23,
|
||||
DT_BIND_NOW = 24,
|
||||
DT_INIT_ARRAY = 25,
|
||||
DT_FINI_ARRAY = 26,
|
||||
DT_INIT_ARRAYSZ = 27,
|
||||
DT_FINI_ARRAYSZ = 28,
|
||||
DT_RUNPATH = 29,
|
||||
DT_FLAGS = 30,
|
||||
DT_ENCODING = 32,
|
||||
DT_PREINIT_ARRAY = 33,
|
||||
DT_PREINIT_ARRAYSZ = 33,
|
||||
DT_LOOS = 0x6000000d,
|
||||
DT_HIOS = 0x6ffff000,
|
||||
DT_LOPROC = 0x70000000,
|
||||
DT_HIPROC = 0x7fffffff,
|
||||
|
||||
// The remaining values are extensions used by GNU or Solaris.
|
||||
DT_VALRNGLO = 0x6ffffd00,
|
||||
DT_GNU_PRELINKED = 0x6ffffdf5,
|
||||
DT_GNU_CONFLICTSZ = 0x6ffffdf6,
|
||||
DT_GNU_LIBLISTSZ = 0x6ffffdf7,
|
||||
DT_CHECKSUM = 0x6ffffdf8,
|
||||
DT_PLTPADSZ = 0x6ffffdf9,
|
||||
DT_MOVEENT = 0x6ffffdfa,
|
||||
DT_MOVESZ = 0x6ffffdfb,
|
||||
DT_FEATURE = 0x6ffffdfc,
|
||||
DT_POSFLAG_1 = 0x6ffffdfd,
|
||||
DT_SYMINSZ = 0x6ffffdfe,
|
||||
DT_SYMINENT = 0x6ffffdff,
|
||||
DT_VALRNGHI = 0x6ffffdff,
|
||||
|
||||
DT_ADDRRNGLO = 0x6ffffe00,
|
||||
DT_GNU_HASH = 0x6ffffef5,
|
||||
DT_TLSDESC_PLT = 0x6ffffef6,
|
||||
DT_TLSDESC_GOT = 0x6ffffef7,
|
||||
DT_GNU_CONFLICT = 0x6ffffef8,
|
||||
DT_GNU_LIBLIST = 0x6ffffef9,
|
||||
DT_CONFIG = 0x6ffffefa,
|
||||
DT_DEPAUDIT = 0x6ffffefb,
|
||||
DT_AUDIT = 0x6ffffefc,
|
||||
DT_PLTPAD = 0x6ffffefd,
|
||||
DT_MOVETAB = 0x6ffffefe,
|
||||
DT_SYMINFO = 0x6ffffeff,
|
||||
DT_ADDRRNGHI = 0x6ffffeff,
|
||||
|
||||
DT_RELACOUNT = 0x6ffffff9,
|
||||
DT_RELCOUNT = 0x6ffffffa,
|
||||
DT_FLAGS_1 = 0x6ffffffb,
|
||||
DT_VERDEF = 0x6ffffffc,
|
||||
DT_VERDEFNUM = 0x6ffffffd,
|
||||
DT_VERNEED = 0x6ffffffe,
|
||||
DT_VERNEEDNUM = 0x6fffffff,
|
||||
|
||||
DT_VERSYM = 0x6ffffff0,
|
||||
|
||||
DT_AUXILIARY = 0x7ffffffd,
|
||||
DT_USED = 0x7ffffffe,
|
||||
DT_FILTER = 0x7fffffff
|
||||
};
|
||||
|
||||
// Flags found in the DT_FLAGS dynamic element.
|
||||
|
||||
enum DF
|
||||
{
|
||||
DF_ORIGIN = 0x1,
|
||||
DF_SYMBOLIC = 0x2,
|
||||
DF_TEXTREL = 0x4,
|
||||
DF_BIND_NOW = 0x8,
|
||||
DF_STATIC_TLS = 0x10
|
||||
};
|
||||
|
||||
// Version numbers which appear in the vd_version field of a Verdef
|
||||
// structure.
|
||||
|
||||
const int VER_DEF_NONE = 0;
|
||||
const int VER_DEF_CURRENT = 1;
|
||||
|
||||
// Version numbers which appear in the vn_version field of a Verneed
|
||||
// structure.
|
||||
|
||||
const int VER_NEED_NONE = 0;
|
||||
const int VER_NEED_CURRENT = 1;
|
||||
|
||||
// Bit flags which appear in vd_flags of Verdef and vna_flags of
|
||||
// Vernaux.
|
||||
|
||||
const int VER_FLG_BASE = 0x1;
|
||||
const int VER_FLG_WEAK = 0x2;
|
||||
|
||||
// Special constants found in the SHT_GNU_versym entries.
|
||||
|
||||
const int VER_NDX_LOCAL = 0;
|
||||
const int VER_NDX_GLOBAL = 1;
|
||||
|
||||
// A SHT_GNU_versym section holds 16-bit words. This bit is set if
|
||||
// the symbol is hidden and can only be seen when referenced using an
|
||||
// explicit version number. This is a GNU extension.
|
||||
|
||||
const int VERSYM_HIDDEN = 0x8000;
|
||||
|
||||
// This is the mask for the rest of the data in a word read from a
|
||||
// SHT_GNU_versym section.
|
||||
|
||||
const int VERSYM_VERSION = 0x7fff;
|
||||
|
||||
} // End namespace elfcpp.
|
||||
|
||||
// Include internal details after defining the types.
|
||||
|
@ -558,6 +690,8 @@ struct Elf_sizes
|
|||
// Sizes of ELF reloc entries.
|
||||
static const int rel_size = sizeof(internal::Rel_data<size>);
|
||||
static const int rela_size = sizeof(internal::Rela_data<size>);
|
||||
// Size of ELF dynamic entry.
|
||||
static const int dyn_size = sizeof(internal::Dyn_data<size>);
|
||||
};
|
||||
|
||||
// Accessor class for the ELF file header.
|
||||
|
@ -1087,6 +1221,198 @@ class Rela
|
|||
const internal::Rela_data<size>* p_;
|
||||
};
|
||||
|
||||
// Accessor classes for entries in the ELF SHT_DYNAMIC section aka
|
||||
// PT_DYNAMIC segment.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Dyn
|
||||
{
|
||||
public:
|
||||
Dyn(const unsigned char* p)
|
||||
: p_(reinterpret_cast<const internal::Dyn_data<size>*>(p))
|
||||
{ }
|
||||
|
||||
template<typename File>
|
||||
Dyn(File* file, typename File::Location loc)
|
||||
: p_(reinterpret_cast<const internal::Dyn_data<size>*>(
|
||||
file->view(loc.file_offset, loc.data_size).data()))
|
||||
{ }
|
||||
|
||||
typename Elf_types<size>::Elf_Swxword
|
||||
get_d_tag() const
|
||||
{ return Convert<size, big_endian>::convert_host(this->p_->d_tag); }
|
||||
|
||||
typename Elf_types<size>::Elf_WXword
|
||||
get_d_val() const
|
||||
{ return Convert<size, big_endian>::convert_host(this->p_->d_val); }
|
||||
|
||||
typename Elf_types<size>::Elf_Addr
|
||||
get_d_ptr() const
|
||||
{ return Convert<size, big_endian>::convert_host(this->p_->d_val); }
|
||||
|
||||
private:
|
||||
const internal::Dyn_data<size>* p_;
|
||||
};
|
||||
|
||||
// Accessor classes for entries in the ELF SHT_GNU_verdef section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Verdef
|
||||
{
|
||||
public:
|
||||
Verdef(const unsigned char* p)
|
||||
: p_(reinterpret_cast<const internal::Verdef_data*>(p))
|
||||
{ }
|
||||
|
||||
template<typename File>
|
||||
Verdef(File* file, typename File::Location loc)
|
||||
: p_(reinterpret_cast<const internal::Verdef_data*>(
|
||||
file->view(loc.file_offset, loc.data_size).data()))
|
||||
{ }
|
||||
|
||||
Elf_Half
|
||||
get_vd_version() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vd_version); }
|
||||
|
||||
Elf_Half
|
||||
get_vd_flags() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vd_flags); }
|
||||
|
||||
Elf_Half
|
||||
get_vd_ndx() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vd_ndx); }
|
||||
|
||||
Elf_Half
|
||||
get_vd_cnt() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vd_cnt); }
|
||||
|
||||
Elf_Word
|
||||
get_vd_hash() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vd_hash); }
|
||||
|
||||
Elf_Word
|
||||
get_vd_aux() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vd_aux); }
|
||||
|
||||
Elf_Word
|
||||
get_vd_next() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vd_next); }
|
||||
|
||||
private:
|
||||
const internal::Verdef_data* p_;
|
||||
};
|
||||
|
||||
// Accessor classes for auxiliary entries in the ELF SHT_GNU_verdef
|
||||
// section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Verdaux
|
||||
{
|
||||
public:
|
||||
Verdaux(const unsigned char* p)
|
||||
: p_(reinterpret_cast<const internal::Verdaux_data*>(p))
|
||||
{ }
|
||||
|
||||
template<typename File>
|
||||
Verdaux(File* file, typename File::Location loc)
|
||||
: p_(reinterpret_cast<const internal::Verdaux_data*>(
|
||||
file->view(loc.file_offset, loc.data_size).data()))
|
||||
{ }
|
||||
|
||||
Elf_Word
|
||||
get_vda_name() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vda_name); }
|
||||
|
||||
Elf_Word
|
||||
get_vda_next() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vda_next); }
|
||||
|
||||
private:
|
||||
const internal::Verdaux_data* p_;
|
||||
};
|
||||
|
||||
// Accessor classes for entries in the ELF SHT_GNU_verneed section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Verneed
|
||||
{
|
||||
public:
|
||||
Verneed(const unsigned char* p)
|
||||
: p_(reinterpret_cast<const internal::Verneed_data*>(p))
|
||||
{ }
|
||||
|
||||
template<typename File>
|
||||
Verneed(File* file, typename File::Location loc)
|
||||
: p_(reinterpret_cast<const internal::Verneed_data*>(
|
||||
file->view(loc.file_offset, loc.data_size).data()))
|
||||
{ }
|
||||
|
||||
Elf_Half
|
||||
get_vn_version() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vn_version); }
|
||||
|
||||
Elf_Half
|
||||
get_vn_cnt() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vn_cnt); }
|
||||
|
||||
Elf_Word
|
||||
get_vn_file() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vn_file); }
|
||||
|
||||
Elf_Word
|
||||
get_vn_aux() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vn_aux); }
|
||||
|
||||
Elf_Word
|
||||
get_vn_next() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vn_next); }
|
||||
|
||||
private:
|
||||
const internal::Verneed_data* p_;
|
||||
};
|
||||
|
||||
// Accessor classes for auxiliary entries in the ELF SHT_GNU_verneed
|
||||
// section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Vernaux
|
||||
{
|
||||
public:
|
||||
Vernaux(const unsigned char* p)
|
||||
: p_(reinterpret_cast<const internal::Vernaux_data*>(p))
|
||||
{ }
|
||||
|
||||
template<typename File>
|
||||
Vernaux(File* file, typename File::Location loc)
|
||||
: p_(reinterpret_cast<const internal::Vernaux_data*>(
|
||||
file->view(loc.file_offset, loc.data_size).data()))
|
||||
{ }
|
||||
|
||||
Elf_Word
|
||||
get_vna_hash() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vna_hash); }
|
||||
|
||||
Elf_Half
|
||||
get_vna_flags() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vna_flags); }
|
||||
|
||||
Elf_Half
|
||||
get_vna_other() const
|
||||
{ return Convert<16, big_endian>::convert_host(this->p_->vna_other); }
|
||||
|
||||
Elf_Word
|
||||
get_vna_name() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vna_name); }
|
||||
|
||||
Elf_Word
|
||||
get_vna_next() const
|
||||
{ return Convert<32, big_endian>::convert_host(this->p_->vna_next); }
|
||||
|
||||
private:
|
||||
const internal::Vernaux_data* p_;
|
||||
};
|
||||
|
||||
|
||||
} // End namespace elfcpp.
|
||||
|
||||
#endif // !defined(ELFPCP_H)
|
||||
|
|
|
@ -35,7 +35,7 @@ struct Ehdr_data
|
|||
Elf_Half e_shstrndx;
|
||||
};
|
||||
|
||||
// An Elf section header.
|
||||
// An ELF section header.
|
||||
|
||||
template<int size>
|
||||
struct Shdr_data
|
||||
|
@ -114,7 +114,7 @@ struct Sym_data<64>
|
|||
Elf_Xword st_size;
|
||||
};
|
||||
|
||||
// Elf relocation table entries.
|
||||
// ELF relocation table entries.
|
||||
|
||||
template<int size>
|
||||
struct Rel_data
|
||||
|
@ -131,6 +131,81 @@ struct Rela_data
|
|||
typename Elf_types<size>::Elf_Swxword r_addend;
|
||||
};
|
||||
|
||||
// An entry in the ELF SHT_DYNAMIC section aka PT_DYNAMIC segment.
|
||||
|
||||
template<int size>
|
||||
struct Dyn_data
|
||||
{
|
||||
typename Elf_types<size>::Elf_Swxword d_tag;
|
||||
typename Elf_types<size>::Elf_WXword d_val;
|
||||
};
|
||||
|
||||
// An entry in a SHT_GNU_verdef section. This structure is the same
|
||||
// in 32-bit and 64-bit ELF files.
|
||||
|
||||
struct Verdef_data
|
||||
{
|
||||
// Version number of structure (VER_DEF_*).
|
||||
Elf_Half vd_version;
|
||||
// Bit flags (VER_FLG_*).
|
||||
Elf_Half vd_flags;
|
||||
// Version index.
|
||||
Elf_Half vd_ndx;
|
||||
// Number of auxiliary Verdaux entries.
|
||||
Elf_Half vd_cnt;
|
||||
// Hash of name.
|
||||
Elf_Word vd_hash;
|
||||
// Byte offset to first Verdaux entry.
|
||||
Elf_Word vd_aux;
|
||||
// Byte offset to next Verdef entry.
|
||||
Elf_Word vd_next;
|
||||
};
|
||||
|
||||
// An auxiliary entry in a SHT_GNU_verdef section. This structure is
|
||||
// the same in 32-bit and 64-bit ELF files.
|
||||
|
||||
struct Verdaux_data
|
||||
{
|
||||
// Offset in string table of version name.
|
||||
Elf_Word vda_name;
|
||||
// Byte offset to next Verdaux entry.
|
||||
Elf_Word vda_next;
|
||||
};
|
||||
|
||||
// An entry in a SHT_GNU_verneed section. This structure is the same
|
||||
// in 32-bit and 64-bit ELF files.
|
||||
|
||||
struct Verneed_data
|
||||
{
|
||||
// Version number of structure (VER_NEED_*).
|
||||
Elf_Half vn_version;
|
||||
// Number of auxiliary Vernaux entries.
|
||||
Elf_Half vn_cnt;
|
||||
// Offset in string table of library name.
|
||||
Elf_Word vn_file;
|
||||
// Byte offset to first Vernaux entry.
|
||||
Elf_Word vn_aux;
|
||||
// Byt eoffset to next Verneed entry.
|
||||
Elf_Word vn_next;
|
||||
};
|
||||
|
||||
// An auxiliary entry in a SHT_GNU_verneed section. This structure is
|
||||
// the same in 32-bit and 64-bit ELF files.
|
||||
|
||||
struct Vernaux_data
|
||||
{
|
||||
// Hash of dependency name.
|
||||
Elf_Word vna_hash;
|
||||
// Bit flags (VER_FLG_*).
|
||||
Elf_Half vna_flags;
|
||||
// Version index used in SHT_GNU_versym entries.
|
||||
Elf_Half vna_other;
|
||||
// Offset in string table of version name.
|
||||
Elf_Word vna_name;
|
||||
// Byte offset to next Vernaux entry.
|
||||
Elf_Word vna_next;
|
||||
};
|
||||
|
||||
} // End namespace internal.
|
||||
|
||||
} // End namespace elfcpp.
|
||||
|
|
|
@ -15,6 +15,8 @@ INCLUDES = -D_GNU_SOURCE \
|
|||
-DLOCALEDIR="\"$(datadir)/locale\"" \
|
||||
@INCINTL@
|
||||
|
||||
YFLAGS = -d
|
||||
|
||||
noinst_PROGRAMS = ld-new
|
||||
|
||||
CCFILES = \
|
||||
|
@ -22,6 +24,7 @@ CCFILES = \
|
|||
common.cc \
|
||||
defstd.cc \
|
||||
dirsearch.cc \
|
||||
dynobj.cc \
|
||||
fileread.cc \
|
||||
gold.cc \
|
||||
gold-threads.cc \
|
||||
|
@ -32,6 +35,7 @@ CCFILES = \
|
|||
readsyms.cc \
|
||||
reloc.cc \
|
||||
resolve.cc \
|
||||
script.cc \
|
||||
symtab.cc \
|
||||
stringpool.cc \
|
||||
target-select.cc \
|
||||
|
@ -42,6 +46,7 @@ HFILES = \
|
|||
common.h \
|
||||
defstd.h \
|
||||
dirsearch.h \
|
||||
dynobj.h \
|
||||
fileread.h \
|
||||
gold.h \
|
||||
gold-threads.h \
|
||||
|
@ -51,6 +56,7 @@ HFILES = \
|
|||
output.h \
|
||||
readsyms.h \
|
||||
reloc.h \
|
||||
script.h \
|
||||
stringpool.h \
|
||||
symtab.h \
|
||||
target.h \
|
||||
|
@ -61,7 +67,10 @@ HFILES = \
|
|||
TARGETFILES = \
|
||||
i386.cc
|
||||
|
||||
OFILES = gold.o options.o
|
||||
YFILES = \
|
||||
yyscript.y
|
||||
|
||||
EXTRA_DIST = yyscript.c yyscript.h
|
||||
|
||||
POTFILES= $(CCFILES) $(HFILES) $(TARGETFILES)
|
||||
|
||||
|
@ -69,10 +78,13 @@ po/POTFILES.in: @MAINT@ Makefile
|
|||
for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
|
||||
&& mv tmp $(srcdir)/po/POTFILES.in
|
||||
|
||||
ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES)
|
||||
ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES) $(YFILES)
|
||||
ld_new_DEPENDENCIES = $(LIBINTL_DEP)
|
||||
ld_new_LDADD = $(LIBINTL)
|
||||
|
||||
# Use an explicit dependency for the bison generated header file.
|
||||
script.$(OBJEXT): yyscript.h
|
||||
|
||||
.PHONY: install-exec-local
|
||||
|
||||
install-exec-local: ld-new$(EXEEXT)
|
||||
|
|
|
@ -45,7 +45,8 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \
|
|||
$(srcdir)/../install-sh $(srcdir)/../missing \
|
||||
$(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.in \
|
||||
$(top_srcdir)/configure $(top_srcdir)/po/Make-in
|
||||
$(top_srcdir)/configure $(top_srcdir)/po/Make-in yyscript.c \
|
||||
yyscript.h
|
||||
subdir = .
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
|
||||
|
@ -63,29 +64,32 @@ CONFIG_HEADER = config.h
|
|||
CONFIG_CLEAN_FILES = po/Makefile.in
|
||||
PROGRAMS = $(noinst_PROGRAMS)
|
||||
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \
|
||||
dirsearch.$(OBJEXT) fileread.$(OBJEXT) gold.$(OBJEXT) \
|
||||
gold-threads.$(OBJEXT) layout.$(OBJEXT) object.$(OBJEXT) \
|
||||
options.$(OBJEXT) output.$(OBJEXT) readsyms.$(OBJEXT) \
|
||||
reloc.$(OBJEXT) resolve.$(OBJEXT) symtab.$(OBJEXT) \
|
||||
stringpool.$(OBJEXT) target-select.$(OBJEXT) \
|
||||
workqueue.$(OBJEXT)
|
||||
dirsearch.$(OBJEXT) dynobj.$(OBJEXT) fileread.$(OBJEXT) \
|
||||
gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
|
||||
object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
|
||||
readsyms.$(OBJEXT) reloc.$(OBJEXT) resolve.$(OBJEXT) \
|
||||
script.$(OBJEXT) symtab.$(OBJEXT) stringpool.$(OBJEXT) \
|
||||
target-select.$(OBJEXT) workqueue.$(OBJEXT)
|
||||
am__objects_2 =
|
||||
am__objects_3 = i386.$(OBJEXT)
|
||||
am_ld_new_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3)
|
||||
am__objects_4 = yyscript.$(OBJEXT)
|
||||
am_ld_new_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4)
|
||||
ld_new_OBJECTS = $(am_ld_new_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
|
||||
depcomp = $(SHELL) $(top_srcdir)/../depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
|
||||
SOURCES = $(ld_new_SOURCES)
|
||||
DIST_SOURCES = $(ld_new_SOURCES)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
|
@ -175,6 +179,7 @@ VERSION = @VERSION@
|
|||
WARN_CFLAGS = @WARN_CFLAGS@
|
||||
WARN_CXXFLAGS = @WARN_CXXFLAGS@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
YACC = @YACC@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
|
@ -229,11 +234,13 @@ INCLUDES = -D_GNU_SOURCE \
|
|||
-DLOCALEDIR="\"$(datadir)/locale\"" \
|
||||
@INCINTL@
|
||||
|
||||
YFLAGS = -d
|
||||
CCFILES = \
|
||||
archive.cc \
|
||||
common.cc \
|
||||
defstd.cc \
|
||||
dirsearch.cc \
|
||||
dynobj.cc \
|
||||
fileread.cc \
|
||||
gold.cc \
|
||||
gold-threads.cc \
|
||||
|
@ -244,6 +251,7 @@ CCFILES = \
|
|||
readsyms.cc \
|
||||
reloc.cc \
|
||||
resolve.cc \
|
||||
script.cc \
|
||||
symtab.cc \
|
||||
stringpool.cc \
|
||||
target-select.cc \
|
||||
|
@ -254,6 +262,7 @@ HFILES = \
|
|||
common.h \
|
||||
defstd.h \
|
||||
dirsearch.h \
|
||||
dynobj.h \
|
||||
fileread.h \
|
||||
gold.h \
|
||||
gold-threads.h \
|
||||
|
@ -263,6 +272,7 @@ HFILES = \
|
|||
output.h \
|
||||
readsyms.h \
|
||||
reloc.h \
|
||||
script.h \
|
||||
stringpool.h \
|
||||
symtab.h \
|
||||
target.h \
|
||||
|
@ -273,16 +283,19 @@ HFILES = \
|
|||
TARGETFILES = \
|
||||
i386.cc
|
||||
|
||||
OFILES = gold.o options.o
|
||||
YFILES = \
|
||||
yyscript.y
|
||||
|
||||
EXTRA_DIST = yyscript.c yyscript.h
|
||||
POTFILES = $(CCFILES) $(HFILES) $(TARGETFILES)
|
||||
ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES)
|
||||
ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES) $(YFILES)
|
||||
ld_new_DEPENDENCIES = $(LIBINTL_DEP)
|
||||
ld_new_LDADD = $(LIBINTL)
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cc .o .obj
|
||||
.SUFFIXES: .c .cc .o .obj .y
|
||||
am--refresh:
|
||||
@:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
|
@ -338,6 +351,11 @@ po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
|
|||
|
||||
clean-noinstPROGRAMS:
|
||||
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
|
||||
yyscript.h: yyscript.c
|
||||
@if test ! -f $@; then \
|
||||
rm -f yyscript.c; \
|
||||
$(MAKE) yyscript.c; \
|
||||
else :; fi
|
||||
ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES)
|
||||
@rm -f ld-new$(EXEEXT)
|
||||
$(CXXLINK) $(ld_new_LDFLAGS) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS)
|
||||
|
@ -352,6 +370,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defstd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirsearch.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynobj.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileread.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold-threads.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@
|
||||
|
@ -363,10 +382,26 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readsyms.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reloc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringpool.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target-select.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workqueue.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yyscript.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cc.o:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
|
@ -381,6 +416,27 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.y.c:
|
||||
$(YACCCOMPILE) $<
|
||||
if test -f y.tab.h; then \
|
||||
to=`echo "$*_H" | sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`; \
|
||||
sed -e "/^#/!b" -e "s/Y_TAB_H/$$to/g" -e "s|y\.tab\.h|$*.h|" \
|
||||
y.tab.h >$*.ht; \
|
||||
rm -f y.tab.h; \
|
||||
if cmp -s $*.ht $*.h; then \
|
||||
rm -f $*.ht ;\
|
||||
else \
|
||||
mv $*.ht $*.h; \
|
||||
fi; \
|
||||
fi
|
||||
if test -f y.output; then \
|
||||
mv y.output $*.output; \
|
||||
fi
|
||||
sed '/^#/ s|y\.tab\.c|$@|' y.tab.c >$@t && mv $@t $@
|
||||
rm -f y.tab.c
|
||||
uninstall-info-am:
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
|
@ -686,6 +742,8 @@ distclean-generic:
|
|||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-rm -f yyscript.c
|
||||
-rm -f yyscript.h
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
|
||||
|
@ -761,6 +819,9 @@ po/POTFILES.in: @MAINT@ Makefile
|
|||
for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
|
||||
&& mv tmp $(srcdir)/po/POTFILES.in
|
||||
|
||||
# Use an explicit dependency for the bison generated header file.
|
||||
script.$(OBJEXT): yyscript.h
|
||||
|
||||
.PHONY: install-exec-local
|
||||
|
||||
install-exec-local: ld-new$(EXEEXT)
|
||||
|
|
|
@ -171,7 +171,7 @@ Symbol_table::do_allocate_commons(const General_options&,
|
|||
|
||||
// Place them in a newly allocated .bss section.
|
||||
|
||||
Output_section_common *poc = new Output_section_common(addralign);
|
||||
Output_data_common *poc = new Output_data_common(addralign);
|
||||
|
||||
layout->add_output_section_data(".bss", elfcpp::SHT_NOBITS,
|
||||
elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC,
|
||||
|
|
44
gold/configure
vendored
44
gold/configure
vendored
|
@ -309,7 +309,7 @@ ac_includes_default="\
|
|||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
@ -3409,6 +3409,47 @@ else
|
|||
fi
|
||||
|
||||
|
||||
for ac_prog in 'bison -y' byacc
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
echo "$as_me:$LINENO: checking for $ac_word" >&5
|
||||
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
|
||||
if test "${ac_cv_prog_YACC+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
if test -n "$YACC"; then
|
||||
ac_cv_prog_YACC="$YACC" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_YACC="$ac_prog"
|
||||
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
fi
|
||||
fi
|
||||
YACC=$ac_cv_prog_YACC
|
||||
if test -n "$YACC"; then
|
||||
echo "$as_me:$LINENO: result: $YACC" >&5
|
||||
echo "${ECHO_T}$YACC" >&6
|
||||
else
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
|
||||
test -n "$YACC" && break
|
||||
done
|
||||
test -n "$YACC" || YACC="yacc"
|
||||
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
# incompatible versions:
|
||||
|
@ -5746,6 +5787,7 @@ s,@ac_ct_CXX@,$ac_ct_CXX,;t t
|
|||
s,@CXXDEPMODE@,$CXXDEPMODE,;t t
|
||||
s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
|
||||
s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
|
||||
s,@YACC@,$YACC,;t t
|
||||
s,@USE_NLS@,$USE_NLS,;t t
|
||||
s,@LIBINTL@,$LIBINTL,;t t
|
||||
s,@LIBINTL_DEP@,$LIBINTL_DEP,;t t
|
||||
|
|
|
@ -12,6 +12,7 @@ AM_CONFIG_HEADER(config.h:config.in)
|
|||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_YACC
|
||||
AC_PROG_INSTALL
|
||||
ZW_GNU_GETTEXT_SISTER_DIR
|
||||
AM_PO_SUBDIRS
|
||||
|
|
670
gold/dynobj.cc
Normal file
670
gold/dynobj.cc
Normal file
|
@ -0,0 +1,670 @@
|
|||
// dynobj.cc -- dynamic object support for gold
|
||||
|
||||
#include "gold.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
#include "symtab.h"
|
||||
#include "dynobj.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
|
||||
// Class Sized_dynobj.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Sized_dynobj<size, big_endian>::Sized_dynobj(
|
||||
const std::string& name,
|
||||
Input_file* input_file,
|
||||
off_t offset,
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Dynobj(name, input_file, offset),
|
||||
elf_file_(this, ehdr),
|
||||
soname_()
|
||||
{
|
||||
}
|
||||
|
||||
// Set up the object.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::setup(
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
{
|
||||
this->set_target(ehdr.get_e_machine(), size, big_endian,
|
||||
ehdr.get_e_ident()[elfcpp::EI_OSABI],
|
||||
ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
|
||||
|
||||
const unsigned int shnum = this->elf_file_.shnum();
|
||||
this->set_shnum(shnum);
|
||||
}
|
||||
|
||||
// Find the SHT_DYNSYM section and the various version sections, and
|
||||
// the dynamic section, given the section headers.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::find_dynsym_sections(
|
||||
const unsigned char* pshdrs,
|
||||
unsigned int* pdynsym_shndx,
|
||||
unsigned int* pversym_shndx,
|
||||
unsigned int* pverdef_shndx,
|
||||
unsigned int* pverneed_shndx,
|
||||
unsigned int* pdynamic_shndx)
|
||||
{
|
||||
*pdynsym_shndx = -1U;
|
||||
*pversym_shndx = -1U;
|
||||
*pverdef_shndx = -1U;
|
||||
*pverneed_shndx = -1U;
|
||||
*pdynamic_shndx = -1U;
|
||||
|
||||
const unsigned int shnum = this->shnum();
|
||||
const unsigned char* p = pshdrs;
|
||||
for (unsigned int i = 0; i < shnum; ++i, p += This::shdr_size)
|
||||
{
|
||||
typename This::Shdr shdr(p);
|
||||
|
||||
unsigned int* pi;
|
||||
switch (shdr.get_sh_type())
|
||||
{
|
||||
case elfcpp::SHT_DYNSYM:
|
||||
pi = pdynsym_shndx;
|
||||
break;
|
||||
case elfcpp::SHT_GNU_versym:
|
||||
pi = pversym_shndx;
|
||||
break;
|
||||
case elfcpp::SHT_GNU_verdef:
|
||||
pi = pverdef_shndx;
|
||||
break;
|
||||
case elfcpp::SHT_GNU_verneed:
|
||||
pi = pverneed_shndx;
|
||||
break;
|
||||
case elfcpp::SHT_DYNAMIC:
|
||||
pi = pdynamic_shndx;
|
||||
break;
|
||||
default:
|
||||
pi = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pi == NULL)
|
||||
continue;
|
||||
|
||||
if (*pi != -1U)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: unexpected duplicate type %u section: %u, %u\n"),
|
||||
program_name, this->name().c_str(), shdr.get_sh_type(),
|
||||
*pi, i);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
*pi = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the contents of section SHNDX. PSHDRS points to the section
|
||||
// headers. TYPE is the expected section type. LINK is the expected
|
||||
// section link. Store the data in *VIEW and *VIEW_SIZE. The
|
||||
// section's sh_info field is stored in *VIEW_INFO.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::read_dynsym_section(
|
||||
const unsigned char* pshdrs,
|
||||
unsigned int shndx,
|
||||
elfcpp::SHT type,
|
||||
unsigned int link,
|
||||
File_view** view,
|
||||
off_t* view_size,
|
||||
unsigned int* view_info)
|
||||
{
|
||||
if (shndx == -1U)
|
||||
{
|
||||
*view = NULL;
|
||||
*view_size = 0;
|
||||
*view_info = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
typename This::Shdr shdr(pshdrs + shndx * This::shdr_size);
|
||||
|
||||
assert(shdr.get_sh_type() == type);
|
||||
|
||||
if (shdr.get_sh_link() != link)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: unexpected link in section %u header: %u != %u\n"),
|
||||
program_name, this->name().c_str(), shndx,
|
||||
shdr.get_sh_link(), link);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
*view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size());
|
||||
*view_size = shdr.get_sh_size();
|
||||
*view_info = shdr.get_sh_info();
|
||||
}
|
||||
|
||||
// Set soname_ if this shared object has a DT_SONAME tag. PSHDRS
|
||||
// points to the section headers. DYNAMIC_SHNDX is the section index
|
||||
// of the SHT_DYNAMIC section. STRTAB_SHNDX, STRTAB, and STRTAB_SIZE
|
||||
// are the section index and contents of a string table which may be
|
||||
// the one associated with the SHT_DYNAMIC section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
||||
unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx,
|
||||
const unsigned char* strtabu,
|
||||
off_t strtab_size)
|
||||
{
|
||||
typename This::Shdr dynamicshdr(pshdrs + dynamic_shndx * This::shdr_size);
|
||||
assert(dynamicshdr.get_sh_type() == elfcpp::SHT_DYNAMIC);
|
||||
|
||||
const off_t dynamic_size = dynamicshdr.get_sh_size();
|
||||
const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(),
|
||||
dynamic_size);
|
||||
|
||||
const unsigned int link = dynamicshdr.get_sh_link();
|
||||
if (link != strtab_shndx)
|
||||
{
|
||||
if (link >= this->shnum())
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: DYNAMIC section %u link out of range: %u\n"),
|
||||
program_name, this->name().c_str(),
|
||||
dynamic_shndx, link);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
typename This::Shdr strtabshdr(pshdrs + link * This::shdr_size);
|
||||
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: DYNAMIC section %u link %u is not a strtab\n"),
|
||||
program_name, this->name().c_str(),
|
||||
dynamic_shndx, link);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
strtab_size = strtabshdr.get_sh_size();
|
||||
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size);
|
||||
}
|
||||
|
||||
for (const unsigned char* p = pdynamic;
|
||||
p < pdynamic + dynamic_size;
|
||||
p += This::dyn_size)
|
||||
{
|
||||
typename This::Dyn dyn(p);
|
||||
|
||||
if (dyn.get_d_tag() == elfcpp::DT_SONAME)
|
||||
{
|
||||
off_t val = dyn.get_d_val();
|
||||
if (val >= strtab_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: DT_SONAME value out of range: "
|
||||
"%lld >= %lld\n"),
|
||||
program_name, this->name().c_str(),
|
||||
static_cast<long long>(val),
|
||||
static_cast<long long>(strtab_size));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const char* strtab = reinterpret_cast<const char*>(strtabu);
|
||||
this->soname_ = std::string(strtab + val);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dyn.get_d_tag() == elfcpp::DT_NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, _("%s: %s: missing DT_NULL in dynamic segment\n"),
|
||||
program_name, this->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
// Read the symbols and sections from a dynamic object. We read the
|
||||
// dynamic symbols, not the normal symbols.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
{
|
||||
this->read_section_data(&this->elf_file_, sd);
|
||||
|
||||
const unsigned char* const pshdrs = sd->section_headers->data();
|
||||
|
||||
unsigned int dynsym_shndx;
|
||||
unsigned int versym_shndx;
|
||||
unsigned int verdef_shndx;
|
||||
unsigned int verneed_shndx;
|
||||
unsigned int dynamic_shndx;
|
||||
this->find_dynsym_sections(pshdrs, &dynsym_shndx, &versym_shndx,
|
||||
&verdef_shndx, &verneed_shndx, &dynamic_shndx);
|
||||
|
||||
unsigned int strtab_shndx = -1U;
|
||||
|
||||
if (dynsym_shndx == -1U)
|
||||
{
|
||||
sd->symbols = NULL;
|
||||
sd->symbols_size = 0;
|
||||
sd->symbol_names = NULL;
|
||||
sd->symbol_names_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the dynamic symbols.
|
||||
typename This::Shdr dynsymshdr(pshdrs + dynsym_shndx * This::shdr_size);
|
||||
assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM);
|
||||
|
||||
sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(),
|
||||
dynsymshdr.get_sh_size());
|
||||
sd->symbols_size = dynsymshdr.get_sh_size();
|
||||
|
||||
// Get the symbol names.
|
||||
strtab_shndx = dynsymshdr.get_sh_link();
|
||||
if (strtab_shndx >= this->shnum())
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: invalid dynamic symbol table name index: %u\n"),
|
||||
program_name, this->name().c_str(), strtab_shndx);
|
||||
gold_exit(false);
|
||||
}
|
||||
typename This::Shdr strtabshdr(pshdrs + strtab_shndx * This::shdr_size);
|
||||
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: dynamic symbol table name section "
|
||||
"has wrong type: %u\n"),
|
||||
program_name, this->name().c_str(),
|
||||
static_cast<unsigned int>(strtabshdr.get_sh_type()));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
sd->symbol_names = this->get_lasting_view(strtabshdr.get_sh_offset(),
|
||||
strtabshdr.get_sh_size());
|
||||
sd->symbol_names_size = strtabshdr.get_sh_size();
|
||||
|
||||
// Get the version information.
|
||||
|
||||
unsigned int dummy;
|
||||
this->read_dynsym_section(pshdrs, versym_shndx, elfcpp::SHT_GNU_versym,
|
||||
dynsym_shndx, &sd->versym, &sd->versym_size,
|
||||
&dummy);
|
||||
|
||||
// We require that the version definition and need section link
|
||||
// to the same string table as the dynamic symbol table. This
|
||||
// is not a technical requirement, but it always happens in
|
||||
// practice. We could change this if necessary.
|
||||
|
||||
this->read_dynsym_section(pshdrs, verdef_shndx, elfcpp::SHT_GNU_verdef,
|
||||
strtab_shndx, &sd->verdef, &sd->verdef_size,
|
||||
&sd->verdef_info);
|
||||
|
||||
this->read_dynsym_section(pshdrs, verneed_shndx, elfcpp::SHT_GNU_verneed,
|
||||
strtab_shndx, &sd->verneed, &sd->verneed_size,
|
||||
&sd->verneed_info);
|
||||
}
|
||||
|
||||
// Read the SHT_DYNAMIC section to find whether this shared object
|
||||
// has a DT_SONAME tag. This doesn't really have anything to do
|
||||
// with reading the symbols, but this is a convenient place to do
|
||||
// it.
|
||||
if (dynamic_shndx != -1U)
|
||||
this->set_soname(pshdrs, dynamic_shndx, strtab_shndx,
|
||||
(sd->symbol_names == NULL
|
||||
? NULL
|
||||
: sd->symbol_names->data()),
|
||||
sd->symbol_names_size);
|
||||
}
|
||||
|
||||
// Lay out the input sections for a dynamic object. We don't want to
|
||||
// include sections from a dynamic object, so all that we actually do
|
||||
// here is check for .gnu.warning sections.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::do_layout(const General_options&,
|
||||
Symbol_table* symtab,
|
||||
Layout*,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
const unsigned int shnum = this->shnum();
|
||||
if (shnum == 0)
|
||||
return;
|
||||
|
||||
// Get the section headers.
|
||||
const unsigned char* pshdrs = sd->section_headers->data();
|
||||
|
||||
// Get the section names.
|
||||
const unsigned char* pnamesu = sd->section_names->data();
|
||||
const char* pnames = reinterpret_cast<const char*>(pnamesu);
|
||||
|
||||
// Skip the first, dummy, section.
|
||||
pshdrs += This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
|
||||
{
|
||||
typename This::Shdr shdr(pshdrs);
|
||||
|
||||
if (shdr.get_sh_name() >= sd->section_names_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: bad section name offset for section %u: %lu\n"),
|
||||
program_name, this->name().c_str(), i,
|
||||
static_cast<unsigned long>(shdr.get_sh_name()));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const char* name = pnames + shdr.get_sh_name();
|
||||
|
||||
this->handle_gnu_warning_section(name, i, symtab);
|
||||
}
|
||||
|
||||
delete sd->section_headers;
|
||||
sd->section_headers = NULL;
|
||||
delete sd->section_names;
|
||||
sd->section_names = NULL;
|
||||
}
|
||||
|
||||
// Add an entry to the vector mapping version numbers to version
|
||||
// strings.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::set_version_map(
|
||||
Version_map* version_map,
|
||||
unsigned int ndx,
|
||||
const char* name) const
|
||||
{
|
||||
assert(ndx < version_map->size());
|
||||
if ((*version_map)[ndx] != NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: duplicate definition for version %u\n"),
|
||||
program_name, this->name().c_str(), ndx);
|
||||
gold_exit(false);
|
||||
}
|
||||
(*version_map)[ndx] = name;
|
||||
}
|
||||
|
||||
// Create a vector mapping version numbers to version strings.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::make_version_map(
|
||||
Read_symbols_data* sd,
|
||||
Version_map* version_map) const
|
||||
{
|
||||
if (sd->verdef == NULL && sd->verneed == NULL)
|
||||
return;
|
||||
|
||||
// First find the largest version index.
|
||||
unsigned int maxver = 0;
|
||||
|
||||
if (sd->verdef != NULL)
|
||||
{
|
||||
const unsigned char* pverdef = sd->verdef->data();
|
||||
off_t verdef_size = sd->verdef_size;
|
||||
const unsigned int count = sd->verdef_info;
|
||||
|
||||
const unsigned char* p = pverdef;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
elfcpp::Verdef<size, big_endian> verdef(p);
|
||||
|
||||
const unsigned int vd_ndx = verdef.get_vd_ndx();
|
||||
|
||||
// The GNU linker clears the VERSYM_HIDDEN bit. I'm not
|
||||
// sure why.
|
||||
|
||||
if (vd_ndx > maxver)
|
||||
maxver = vd_ndx;
|
||||
|
||||
const unsigned int vd_next = verdef.get_vd_next();
|
||||
if ((p - pverdef) + vd_next >= verdef_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verdef vd_next field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vd_next);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
p += vd_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (sd->verneed != NULL)
|
||||
{
|
||||
const unsigned char* pverneed = sd->verneed->data();
|
||||
off_t verneed_size = sd->verneed_size;
|
||||
const unsigned int count = sd->verneed_info;
|
||||
|
||||
const unsigned char* p = pverneed;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
elfcpp::Verneed<size, big_endian> verneed(p);
|
||||
|
||||
const unsigned int vn_aux = verneed.get_vn_aux();
|
||||
if ((p - pverneed) + vn_aux >= verneed_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verneed vn_aux field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vn_aux);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const unsigned int vn_cnt = verneed.get_vn_cnt();
|
||||
const unsigned char* pvna = p + vn_aux;
|
||||
for (unsigned int j = 0; j < vn_cnt; ++j)
|
||||
{
|
||||
elfcpp::Vernaux<size, big_endian> vernaux(pvna);
|
||||
|
||||
const unsigned int vna_other = vernaux.get_vna_other();
|
||||
if (vna_other > maxver)
|
||||
maxver = vna_other;
|
||||
|
||||
const unsigned int vna_next = vernaux.get_vna_next();
|
||||
if ((pvna - pverneed) + vna_next >= verneed_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verneed vna_next field "
|
||||
"out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vna_next);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
pvna += vna_next;
|
||||
}
|
||||
|
||||
const unsigned int vn_next = verneed.get_vn_next();
|
||||
if ((p - pverneed) + vn_next >= verneed_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verneed vn_next field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vn_next);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
p += vn_next;
|
||||
}
|
||||
}
|
||||
|
||||
// Now MAXVER is the largest version index we have seen.
|
||||
|
||||
version_map->resize(maxver + 1);
|
||||
|
||||
const char* names = reinterpret_cast<const char*>(sd->symbol_names->data());
|
||||
off_t names_size = sd->symbol_names_size;
|
||||
|
||||
if (sd->verdef != NULL)
|
||||
{
|
||||
const unsigned char* pverdef = sd->verdef->data();
|
||||
off_t verdef_size = sd->verdef_size;
|
||||
const unsigned int count = sd->verdef_info;
|
||||
|
||||
const unsigned char* p = pverdef;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
elfcpp::Verdef<size, big_endian> verdef(p);
|
||||
|
||||
const unsigned int vd_cnt = verdef.get_vd_cnt();
|
||||
if (vd_cnt < 1)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: verdef vd_cnt field too small: %u\n"),
|
||||
program_name, this->name().c_str(), vd_cnt);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const unsigned int vd_aux = verdef.get_vd_aux();
|
||||
if ((p - pverdef) + vd_aux >= verdef_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verdef vd_aux field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vd_aux);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const unsigned char* pvda = p + vd_aux;
|
||||
elfcpp::Verdaux<size, big_endian> verdaux(pvda);
|
||||
|
||||
const unsigned int vda_name = verdaux.get_vda_name();
|
||||
if (vda_name >= names_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verdaux vda_name field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vda_name);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
this->set_version_map(version_map, verdef.get_vd_ndx(),
|
||||
names + vda_name);
|
||||
|
||||
const unsigned int vd_next = verdef.get_vd_next();
|
||||
if ((p - pverdef) + vd_next >= verdef_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: verdef vd_next field out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vd_next);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
p += vd_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (sd->verneed != NULL)
|
||||
{
|
||||
const unsigned char* pverneed = sd->verneed->data();
|
||||
const unsigned int count = sd->verneed_info;
|
||||
|
||||
const unsigned char* p = pverneed;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
elfcpp::Verneed<size, big_endian> verneed(p);
|
||||
|
||||
const unsigned int vn_aux = verneed.get_vn_aux();
|
||||
const unsigned int vn_cnt = verneed.get_vn_cnt();
|
||||
const unsigned char* pvna = p + vn_aux;
|
||||
for (unsigned int j = 0; j < vn_cnt; ++j)
|
||||
{
|
||||
elfcpp::Vernaux<size, big_endian> vernaux(pvna);
|
||||
|
||||
const unsigned int vna_name = vernaux.get_vna_name();
|
||||
if (vna_name >= names_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: vernaux vna_name field "
|
||||
"out of range: %u\n"),
|
||||
program_name, this->name().c_str(), vna_name);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
this->set_version_map(version_map, vernaux.get_vna_other(),
|
||||
names + vna_name);
|
||||
|
||||
pvna += vernaux.get_vna_next();
|
||||
}
|
||||
|
||||
p += verneed.get_vn_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the dynamic symbols to the symbol table.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
if (sd->symbols == NULL)
|
||||
{
|
||||
assert(sd->symbol_names == NULL);
|
||||
assert(sd->versym == NULL && sd->verdef == NULL && sd->verneed == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
const int sym_size = This::sym_size;
|
||||
const size_t symcount = sd->symbols_size / sym_size;
|
||||
if (symcount * sym_size != sd->symbols_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: size of dynamic symbols is not "
|
||||
"multiple of symbol size\n"),
|
||||
program_name, this->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
Version_map version_map;
|
||||
this->make_version_map(sd, &version_map);
|
||||
|
||||
const char* sym_names =
|
||||
reinterpret_cast<const char*>(sd->symbol_names->data());
|
||||
symtab->add_from_dynobj(this, sd->symbols->data(), symcount,
|
||||
sym_names, sd->symbol_names_size,
|
||||
(sd->versym == NULL
|
||||
? NULL
|
||||
: sd->versym->data()),
|
||||
sd->versym_size,
|
||||
&version_map);
|
||||
|
||||
delete sd->symbols;
|
||||
sd->symbols = NULL;
|
||||
delete sd->symbol_names;
|
||||
sd->symbol_names = NULL;
|
||||
if (sd->versym != NULL)
|
||||
{
|
||||
delete sd->versym;
|
||||
sd->versym = NULL;
|
||||
}
|
||||
if (sd->verdef != NULL)
|
||||
{
|
||||
delete sd->verdef;
|
||||
sd->verdef = NULL;
|
||||
}
|
||||
if (sd->verneed != NULL)
|
||||
{
|
||||
delete sd->verneed;
|
||||
sd->verneed = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate the templates we need. We could use the configure
|
||||
// script to restrict this to only the ones for implemented targets.
|
||||
|
||||
template
|
||||
class Sized_dynobj<32, false>;
|
||||
|
||||
template
|
||||
class Sized_dynobj<32, true>;
|
||||
|
||||
template
|
||||
class Sized_dynobj<64, false>;
|
||||
|
||||
template
|
||||
class Sized_dynobj<64, true>;
|
||||
|
||||
} // End namespace gold.
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef GOLD_DYNOBJ_H
|
||||
#define GOLD_DYNOBJ_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gold
|
||||
|
@ -28,6 +30,10 @@ class Sized_dynobj : public Dynobj
|
|||
Sized_dynobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>&);
|
||||
|
||||
// Set up the object file based on the ELF header.
|
||||
void
|
||||
setup(const typename elfcpp::Ehdr<size, big_endian>&);
|
||||
|
||||
// Read the symbols.
|
||||
void
|
||||
do_read_symbols(Read_symbols_data*);
|
||||
|
@ -41,14 +47,65 @@ class Sized_dynobj : public Dynobj
|
|||
void
|
||||
do_add_symbols(Symbol_table*, Read_symbols_data*);
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size.
|
||||
const unsigned char*
|
||||
do_section_contents(unsigned int shnum, off_t* plen) = 0;
|
||||
|
||||
// Get the name of a section.
|
||||
std::string
|
||||
do_section_name(unsigned int shnum);
|
||||
do_section_name(unsigned int shndx)
|
||||
{ return this->elf_file_.section_name(shndx); }
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size.
|
||||
Object::Location
|
||||
do_section_contents(unsigned int shndx)
|
||||
{ return this->elf_file_.section_contents(shndx); }
|
||||
|
||||
private:
|
||||
// For convenience.
|
||||
typedef Sized_dynobj<size, big_endian> This;
|
||||
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||
static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
static const int dyn_size = elfcpp::Elf_sizes<size>::dyn_size;
|
||||
typedef elfcpp::Shdr<size, big_endian> Shdr;
|
||||
typedef elfcpp::Dyn<size, big_endian> Dyn;
|
||||
|
||||
// Find the dynamic symbol table and the version sections, given the
|
||||
// section headers.
|
||||
void
|
||||
find_dynsym_sections(const unsigned char* pshdrs,
|
||||
unsigned int* pdynshm_shndx,
|
||||
unsigned int* pversym_shndx,
|
||||
unsigned int* pverdef_shndx,
|
||||
unsigned int* pverneed_shndx,
|
||||
unsigned int* pdynamic_shndx);
|
||||
|
||||
// Read the dynamic symbol section SHNDX.
|
||||
void
|
||||
read_dynsym_section(const unsigned char* pshdrs, unsigned int shndx,
|
||||
elfcpp::SHT type, unsigned int link,
|
||||
File_view** view, off_t* view_size,
|
||||
unsigned int* view_info);
|
||||
|
||||
// Set the SONAME from the SHT_DYNAMIC section at DYNAMIC_SHNDX.
|
||||
// The STRTAB parameters may have the relevant string table.
|
||||
void
|
||||
set_soname(const unsigned char* pshdrs, unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx, const unsigned char* strtabu,
|
||||
off_t strtab_size);
|
||||
|
||||
// Mapping from version number to version name.
|
||||
typedef std::vector<const char*> Version_map;
|
||||
|
||||
// Create the version map.
|
||||
void
|
||||
make_version_map(Read_symbols_data* sd, Version_map*) const;
|
||||
|
||||
// Add an entry to the version map.
|
||||
void
|
||||
set_version_map(Version_map*, unsigned int ndx, const char* name) const;
|
||||
|
||||
// General access to the ELF file.
|
||||
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
|
||||
// The DT_SONAME name, if any.
|
||||
std::string soname_;
|
||||
};
|
||||
|
||||
} // End namespace gold.
|
||||
|
|
|
@ -113,7 +113,7 @@ queue_initial_tasks(const General_options& options,
|
|||
Task_token* next_blocker = new Task_token();
|
||||
next_blocker->add_blocker();
|
||||
workqueue->queue(new Read_symbols(options, input_objects, symtab, layout,
|
||||
search_path, *p, NULL, this_blocker,
|
||||
search_path, &*p, NULL, this_blocker,
|
||||
next_blocker));
|
||||
this_blocker = next_blocker;
|
||||
}
|
||||
|
|
20
gold/i386.cc
20
gold/i386.cc
|
@ -149,7 +149,7 @@ class Target_i386 : public Sized_target<32, false>
|
|||
optimize_tls_reloc(const General_options*, bool is_local, int r_type);
|
||||
|
||||
// Get the GOT section, creating it if necessary.
|
||||
Output_section_got<32, false>*
|
||||
Output_data_got<32, false>*
|
||||
got_section(Symbol_table*, Layout*);
|
||||
|
||||
// Information about this specific target which we pass to the
|
||||
|
@ -157,7 +157,7 @@ class Target_i386 : public Sized_target<32, false>
|
|||
static const Target::Target_info i386_info;
|
||||
|
||||
// The GOT section.
|
||||
Output_section_got<32, false>* got_;
|
||||
Output_data_got<32, false>* got_;
|
||||
};
|
||||
|
||||
const Target::Target_info Target_i386::i386_info =
|
||||
|
@ -166,20 +166,21 @@ const Target::Target_info Target_i386::i386_info =
|
|||
false, // is_big_endian
|
||||
elfcpp::EM_386, // machine_code
|
||||
false, // has_make_symbol
|
||||
false, // has_resolve,
|
||||
0x08048000, // text_segment_address,
|
||||
false, // has_resolve
|
||||
"/usr/lib/libc.so.1", // dynamic_linker
|
||||
0x08048000, // text_segment_address
|
||||
0x1000, // abi_pagesize
|
||||
0x1000 // common_pagesize
|
||||
};
|
||||
|
||||
// Get the GOT section, creating it if necessary.
|
||||
|
||||
Output_section_got<32, false>*
|
||||
Output_data_got<32, false>*
|
||||
Target_i386::got_section(Symbol_table* symtab, Layout* layout)
|
||||
{
|
||||
if (this->got_ == NULL)
|
||||
{
|
||||
this->got_ = new Output_section_got<32, false>();
|
||||
this->got_ = new Output_data_got<32, false>();
|
||||
|
||||
assert(symtab != NULL && layout != NULL);
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
|
@ -393,13 +394,8 @@ Target_i386::Scan::global(const General_options& options,
|
|||
|
||||
case elfcpp::R_386_GOT32:
|
||||
// The symbol requires a GOT entry.
|
||||
if (!gsym->has_got_offset())
|
||||
if (target->got_section(symtab, layout)->add_global(gsym))
|
||||
{
|
||||
Output_section_got<32, false>* got = target->got_section(symtab,
|
||||
layout);
|
||||
const unsigned int got_offset = got->add_global(gsym);
|
||||
gsym->set_got_offset(got_offset);
|
||||
|
||||
// If this symbol is not resolved locally, we need to add a
|
||||
// dynamic relocation for it.
|
||||
if (!gsym->is_resolved_locally())
|
||||
|
|
|
@ -355,13 +355,30 @@ Layout::find_first_load_seg()
|
|||
off_t
|
||||
Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
|
||||
{
|
||||
const int size = input_objects->target()->get_size();
|
||||
|
||||
Output_segment* phdr_seg = NULL;
|
||||
if (input_objects->any_dynamic())
|
||||
{
|
||||
// If there are any dynamic objects in the link, then we need
|
||||
// some additional segments: PT_PHDRS, PT_INTERP, and
|
||||
// PT_DYNAMIC. We also need to finalize the dynamic symbol
|
||||
// table and create the dynamic hash table.
|
||||
abort();
|
||||
// There was a dynamic object in the link. We need to create
|
||||
// some information for the dynamic linker.
|
||||
|
||||
// Create the PT_PHDR segment which will hold the program
|
||||
// headers.
|
||||
phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
|
||||
this->segment_list_.push_back(phdr_seg);
|
||||
|
||||
// Create the dynamic symbol table, including the hash table,
|
||||
// the dynamic relocations, and the version sections.
|
||||
this->create_dynamic_symtab(size, symtab);
|
||||
|
||||
// Create the .dynamic section to hold the dynamic data, and put
|
||||
// it in a PT_DYNAMIC segment.
|
||||
this->create_dynamic_section();
|
||||
|
||||
// Create the .interp section to hold the name of the
|
||||
// interpreter, and put it in a PT_INTERP segment.
|
||||
this->create_interp(input_objects->target());
|
||||
}
|
||||
|
||||
// FIXME: Handle PT_GNU_STACK.
|
||||
|
@ -369,14 +386,14 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
|
|||
Output_segment* load_seg = this->find_first_load_seg();
|
||||
|
||||
// Lay out the segment headers.
|
||||
int size = input_objects->target()->get_size();
|
||||
bool big_endian = input_objects->target()->is_big_endian();
|
||||
Output_segment_headers* segment_headers;
|
||||
segment_headers = new Output_segment_headers(size, big_endian,
|
||||
this->segment_list_);
|
||||
load_seg->add_initial_output_data(segment_headers);
|
||||
this->special_output_list_.push_back(segment_headers);
|
||||
// FIXME: Attach them to PT_PHDRS if necessary.
|
||||
if (phdr_seg != NULL)
|
||||
phdr_seg->add_initial_output_data(segment_headers);
|
||||
|
||||
// Lay out the file header.
|
||||
Output_file_header* file_header;
|
||||
|
@ -736,6 +753,49 @@ Layout::create_shdrs(int size, bool big_endian, off_t* poff)
|
|||
return oshdrs;
|
||||
}
|
||||
|
||||
// Create the dynamic symbol table.
|
||||
|
||||
void
|
||||
Layout::create_dynamic_symtab(int, Symbol_table*)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Create the .dynamic section and PT_DYNAMIC segment.
|
||||
|
||||
void
|
||||
Layout::create_dynamic_section()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Create the .interp section and PT_INTERP segment.
|
||||
|
||||
void
|
||||
Layout::create_interp(const Target* target)
|
||||
{
|
||||
const char* interp = this->options_.dynamic_linker();
|
||||
if (interp == NULL)
|
||||
{
|
||||
interp = target->dynamic_linker();
|
||||
assert(interp != NULL);
|
||||
}
|
||||
|
||||
size_t len = strlen(interp) + 1;
|
||||
|
||||
Output_section_data* odata = new Output_data_const(interp, len, 1);
|
||||
|
||||
const char* interp_name = this->namepool_.add(".interp", NULL);
|
||||
Output_section* osec = this->make_output_section(interp_name,
|
||||
elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC);
|
||||
osec->add_output_section_data(odata);
|
||||
|
||||
Output_segment* oseg = new Output_segment(elfcpp::PT_INTERP, elfcpp::PF_R);
|
||||
this->segment_list_.push_back(oseg);
|
||||
oseg->add_initial_output_section(osec, elfcpp::PF_R);
|
||||
}
|
||||
|
||||
// The mapping of .gnu.linkonce section names to real section names.
|
||||
|
||||
#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
|
||||
|
|
|
@ -154,15 +154,6 @@ class Layout
|
|||
Output_segment*
|
||||
find_first_load_seg();
|
||||
|
||||
// Set the final file offsets of all the segments.
|
||||
off_t
|
||||
set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);
|
||||
|
||||
// Set the final file offsets and section indices of all the
|
||||
// sections not associated with a segment.
|
||||
off_t
|
||||
set_section_offsets(off_t, unsigned int *pshndx);
|
||||
|
||||
// Create the output sections for the symbol table.
|
||||
void
|
||||
create_symtab_sections(int size, const Input_objects*, Symbol_table*, off_t*,
|
||||
|
@ -177,6 +168,18 @@ class Layout
|
|||
Output_section_headers*
|
||||
create_shdrs(int size, bool big_endian, off_t*);
|
||||
|
||||
// Create the dynamic symbol table.
|
||||
void
|
||||
create_dynamic_symtab(int size, Symbol_table*);
|
||||
|
||||
// Create the .dynamic section and PT_DYNAMIC segment.
|
||||
void
|
||||
create_dynamic_section();
|
||||
|
||||
// Create the .interp section and PT_INTERP segment.
|
||||
void
|
||||
create_interp(const Target* target);
|
||||
|
||||
// Return whether to include this section in the link.
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
|
@ -204,6 +207,15 @@ class Layout
|
|||
make_output_section(const char* name, elfcpp::Elf_Word type,
|
||||
elfcpp::Elf_Xword flags);
|
||||
|
||||
// Set the final file offsets of all the segments.
|
||||
off_t
|
||||
set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx);
|
||||
|
||||
// Set the final file offsets and section indices of all the
|
||||
// sections not associated with a segment.
|
||||
off_t
|
||||
set_section_offsets(off_t, unsigned int *pshndx);
|
||||
|
||||
// Return whether SEG1 comes before SEG2 in the output file.
|
||||
static bool
|
||||
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
|
||||
|
|
196
gold/object.cc
196
gold/object.cc
|
@ -19,6 +19,22 @@ namespace gold
|
|||
|
||||
// Class Object.
|
||||
|
||||
// Set the target based on fields in the ELF file header.
|
||||
|
||||
void
|
||||
Object::set_target(int machine, int size, bool big_endian, int osabi,
|
||||
int abiversion)
|
||||
{
|
||||
Target* target = select_target(machine, size, big_endian, osabi, abiversion);
|
||||
if (target == NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: unsupported ELF machine number %d\n"),
|
||||
program_name, this->name().c_str(), machine);
|
||||
gold_exit(false);
|
||||
}
|
||||
this->target_ = target;
|
||||
}
|
||||
|
||||
// Report an error for the elfcpp::Elf_file interface.
|
||||
|
||||
void
|
||||
|
@ -45,6 +61,58 @@ Object::section_contents(unsigned int shndx, off_t* plen)
|
|||
return this->get_view(loc.file_offset, loc.data_size);
|
||||
}
|
||||
|
||||
// Read the section data into SD. This is code common to Sized_relobj
|
||||
// and Sized_dynobj, so we put it into Object.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||
|
||||
// Read the section headers.
|
||||
const off_t shoff = elf_file->shoff();
|
||||
const unsigned int shnum = this->shnum();
|
||||
sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size);
|
||||
|
||||
// Read the section names.
|
||||
const unsigned char* pshdrs = sd->section_headers->data();
|
||||
const unsigned char* pshdrnames = pshdrs + elf_file->shstrndx() * shdr_size;
|
||||
typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);
|
||||
|
||||
if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB)
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: section name section has wrong type: %u\n"),
|
||||
program_name, this->name().c_str(),
|
||||
static_cast<unsigned int>(shdrnames.get_sh_type()));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
sd->section_names_size = shdrnames.get_sh_size();
|
||||
sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
|
||||
sd->section_names_size);
|
||||
}
|
||||
|
||||
// If NAME is the name of a special .gnu.warning section, arrange for
|
||||
// the warning to be issued. SHNDX is the section index. Return
|
||||
// whether it is a warning section.
|
||||
|
||||
bool
|
||||
Object::handle_gnu_warning_section(const char* name, unsigned int shndx,
|
||||
Symbol_table* symtab)
|
||||
{
|
||||
const char warn_prefix[] = ".gnu.warning.";
|
||||
const int warn_prefix_len = sizeof warn_prefix - 1;
|
||||
if (strncmp(name, warn_prefix, warn_prefix_len) == 0)
|
||||
{
|
||||
symtab->add_warning(name + warn_prefix_len, this, shndx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Class Sized_relobj.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
|
@ -55,8 +123,7 @@ Sized_relobj<size, big_endian>::Sized_relobj(
|
|||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Relobj(name, input_file, offset),
|
||||
elf_file_(this, ehdr),
|
||||
section_headers_(NULL),
|
||||
symtab_shndx_(0),
|
||||
symtab_shndx_(-1U),
|
||||
local_symbol_count_(0),
|
||||
output_local_symbol_count_(0),
|
||||
symbols_(NULL),
|
||||
|
@ -78,43 +145,41 @@ void
|
|||
Sized_relobj<size, big_endian>::setup(
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
{
|
||||
int machine = ehdr.get_e_machine();
|
||||
Target* target = select_target(machine, size, big_endian,
|
||||
ehdr.get_e_ident()[elfcpp::EI_OSABI],
|
||||
ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
|
||||
if (target == NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: unsupported ELF machine number %d\n"),
|
||||
program_name, this->name().c_str(), machine);
|
||||
gold_exit(false);
|
||||
}
|
||||
this->set_target(target);
|
||||
this->set_target(ehdr.get_e_machine(), size, big_endian,
|
||||
ehdr.get_e_ident()[elfcpp::EI_OSABI],
|
||||
ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
|
||||
|
||||
unsigned int shnum = this->elf_file_.shnum();
|
||||
const unsigned int shnum = this->elf_file_.shnum();
|
||||
this->set_shnum(shnum);
|
||||
if (shnum == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// We store the section headers in a File_view until do_read_symbols.
|
||||
off_t shoff = this->elf_file_.shoff();
|
||||
this->section_headers_ = this->get_lasting_view(shoff,
|
||||
shnum * This::shdr_size);
|
||||
// Find the SHT_SYMTAB section, given the section headers. The ELF
|
||||
// standard says that maybe in the future there can be more than one
|
||||
// SHT_SYMTAB section. Until somebody figures out how that could
|
||||
// work, we assume there is only one.
|
||||
|
||||
// Find the SHT_SYMTAB section. The ELF standard says that maybe in
|
||||
// the future there can be more than one SHT_SYMTAB section. Until
|
||||
// somebody figures out how that could work, we assume there is only
|
||||
// one.
|
||||
const unsigned char* p = this->section_headers_->data();
|
||||
|
||||
// Skip the first section, which is always empty.
|
||||
p += This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_relobj<size, big_endian>::find_symtab(const unsigned char* pshdrs)
|
||||
{
|
||||
const unsigned int shnum = this->shnum();
|
||||
this->symtab_shndx_ = 0;
|
||||
if (shnum > 0)
|
||||
{
|
||||
typename This::Shdr shdr(p);
|
||||
if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
|
||||
// Look through the sections in reverse order, since gas tends
|
||||
// to put the symbol table at the end.
|
||||
const unsigned char* p = pshdrs + shnum * This::shdr_size;
|
||||
unsigned int i = shnum;
|
||||
while (i > 0)
|
||||
{
|
||||
this->symtab_shndx_ = i;
|
||||
break;
|
||||
--i;
|
||||
p -= This::shdr_size;
|
||||
typename This::Shdr shdr(p);
|
||||
if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
|
||||
{
|
||||
this->symtab_shndx_ = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,19 +190,11 @@ template<int size, bool big_endian>
|
|||
void
|
||||
Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
{
|
||||
// Transfer our view of the section headers to SD.
|
||||
sd->section_headers = this->section_headers_;
|
||||
this->section_headers_ = NULL;
|
||||
this->read_section_data(&this->elf_file_, sd);
|
||||
|
||||
// Read the section names.
|
||||
const unsigned char* pshdrs = sd->section_headers->data();
|
||||
const unsigned char* pshdrnames = (pshdrs
|
||||
+ (this->elf_file_.shstrndx()
|
||||
* This::shdr_size));
|
||||
typename This::Shdr shdrnames(pshdrnames);
|
||||
sd->section_names_size = shdrnames.get_sh_size();
|
||||
sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
|
||||
sd->section_names_size);
|
||||
const unsigned char* const pshdrs = sd->section_headers->data();
|
||||
|
||||
this->find_symtab(pshdrs);
|
||||
|
||||
if (this->symtab_shndx_ == 0)
|
||||
{
|
||||
|
@ -166,15 +223,14 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
|||
File_view* fvsymtab = this->get_lasting_view(extoff, extsize);
|
||||
|
||||
// Read the section header for the symbol names.
|
||||
unsigned int shnum = this->shnum();
|
||||
unsigned int strtab_shnum = symtabshdr.get_sh_link();
|
||||
if (strtab_shnum == 0 || strtab_shnum >= shnum)
|
||||
unsigned int strtab_shndx = symtabshdr.get_sh_link();
|
||||
if (strtab_shndx >= this->shnum())
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: invalid symbol table name index: %u\n"),
|
||||
program_name, this->name().c_str(), strtab_shnum);
|
||||
program_name, this->name().c_str(), strtab_shndx);
|
||||
gold_exit(false);
|
||||
}
|
||||
typename This::Shdr strtabshdr(pshdrs + strtab_shnum * This::shdr_size);
|
||||
typename This::Shdr strtabshdr(pshdrs + strtab_shndx * This::shdr_size);
|
||||
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
|
||||
{
|
||||
fprintf(stderr,
|
||||
|
@ -336,7 +392,7 @@ Sized_relobj<size, big_endian>::do_layout(const General_options& options,
|
|||
Layout* layout,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
unsigned int shnum = this->shnum();
|
||||
const unsigned int shnum = this->shnum();
|
||||
if (shnum == 0)
|
||||
return;
|
||||
|
||||
|
@ -353,9 +409,6 @@ Sized_relobj<size, big_endian>::do_layout(const General_options& options,
|
|||
// Keep track of which sections to omit.
|
||||
std::vector<bool> omit(shnum, false);
|
||||
|
||||
const char warn_prefix[] = ".gnu.warning.";
|
||||
const int warn_prefix_len = sizeof warn_prefix - 1;
|
||||
|
||||
// Skip the first, dummy, section.
|
||||
pshdrs += This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
|
||||
|
@ -373,9 +426,8 @@ Sized_relobj<size, big_endian>::do_layout(const General_options& options,
|
|||
|
||||
const char* name = pnames + shdr.get_sh_name();
|
||||
|
||||
if (strncmp(name, warn_prefix, warn_prefix_len) == 0)
|
||||
if (this->handle_gnu_warning_section(name, i, symtab))
|
||||
{
|
||||
symtab->add_warning(name + warn_prefix_len, this, i);
|
||||
if (!options.is_relocatable())
|
||||
omit[i] = true;
|
||||
}
|
||||
|
@ -442,10 +494,8 @@ Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
|||
|
||||
const char* sym_names =
|
||||
reinterpret_cast<const char*>(sd->symbol_names->data());
|
||||
symtab->add_from_object<size, big_endian>(this, sd->symbols->data(),
|
||||
symcount, sym_names,
|
||||
sd->symbol_names_size,
|
||||
this->symbols_);
|
||||
symtab->add_from_relobj(this, sd->symbols->data(), symcount, sym_names,
|
||||
sd->symbol_names_size, this->symbols_);
|
||||
|
||||
delete sd->symbols;
|
||||
sd->symbols = NULL;
|
||||
|
@ -464,6 +514,7 @@ off_t
|
|||
Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
|
||||
Stringpool* pool)
|
||||
{
|
||||
assert(this->symtab_shndx_ != -1U);
|
||||
if (this->symtab_shndx_ == 0)
|
||||
{
|
||||
// This object has no symbols. Weird but legal.
|
||||
|
@ -577,6 +628,7 @@ void
|
|||
Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
const Stringpool* sympool)
|
||||
{
|
||||
assert(this->symtab_shndx_ != -1U);
|
||||
if (this->symtab_shndx_ == 0)
|
||||
{
|
||||
// This object has no symbols. Weird but legal.
|
||||
|
@ -711,13 +763,6 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
|
|||
off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
{
|
||||
int et = ehdr.get_e_type();
|
||||
if (et != elfcpp::ET_REL && et != elfcpp::ET_DYN)
|
||||
{
|
||||
fprintf(stderr, "%s: %s: unsupported ELF type %d\n",
|
||||
program_name, name.c_str(), static_cast<int>(et));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
if (et == elfcpp::ET_REL)
|
||||
{
|
||||
Sized_relobj<size, big_endian>* obj =
|
||||
|
@ -725,17 +770,18 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
|
|||
obj->setup(ehdr);
|
||||
return obj;
|
||||
}
|
||||
else if (et == elfcpp::ET_DYN)
|
||||
{
|
||||
Sized_dynobj<size, big_endian>* obj =
|
||||
new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr);
|
||||
obj->setup(ehdr);
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
// elfcpp::ET_DYN
|
||||
fprintf(stderr, _("%s: %s: dynamic objects are not yet supported\n"),
|
||||
program_name, name.c_str());
|
||||
fprintf(stderr, _("%s: %s: unsupported ELF file type %d\n"),
|
||||
program_name, name.c_str(), et);
|
||||
gold_exit(false);
|
||||
// Sized_dynobj<size, big_endian>* obj =
|
||||
// new Sized_dynobj<size, big_endian>(this->input_.name(), input_file,
|
||||
// offset, ehdr);
|
||||
// obj->setup(ehdr);
|
||||
// return obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,19 @@ struct Read_symbols_data
|
|||
File_view* symbol_names;
|
||||
// Size of symbol name data in bytes.
|
||||
off_t symbol_names_size;
|
||||
|
||||
// Version information. This is only used on dynamic objects.
|
||||
// Version symbol data (from SHT_GNU_versym section).
|
||||
File_view* versym;
|
||||
off_t versym_size;
|
||||
// Version definition data (from SHT_GNU_verdef section).
|
||||
File_view* verdef;
|
||||
off_t verdef_size;
|
||||
unsigned int verdef_info;
|
||||
// Needed version data (from SHT_GNU_verneed section).
|
||||
File_view* verneed;
|
||||
off_t verneed_size;
|
||||
unsigned int verneed_info;
|
||||
};
|
||||
|
||||
// Data about a single relocation section. This is read in
|
||||
|
@ -84,7 +97,7 @@ class Object
|
|||
// file--0 for a .o or .so file, something else for a .a file.
|
||||
Object(const std::string& name, Input_file* input_file, bool is_dynamic,
|
||||
off_t offset = 0)
|
||||
: name_(name), input_file_(input_file), offset_(offset),
|
||||
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
|
||||
is_dynamic_(is_dynamic), target_(NULL)
|
||||
{ }
|
||||
|
||||
|
@ -256,8 +269,33 @@ class Object
|
|||
|
||||
// Set the target.
|
||||
void
|
||||
set_target(Target* target)
|
||||
{ this->target_ = target; }
|
||||
set_target(int machine, int size, bool big_endian, int osabi,
|
||||
int abiversion);
|
||||
|
||||
// Get the number of sections.
|
||||
unsigned int
|
||||
shnum() const
|
||||
{ return this->shnum_; }
|
||||
|
||||
// Set the number of sections.
|
||||
void
|
||||
set_shnum(int shnum)
|
||||
{ this->shnum_ = shnum; }
|
||||
|
||||
// Functions used by both Sized_relobj and Sized_dynobj.
|
||||
|
||||
// Read the section data into a Read_symbols_data object.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
read_section_data(elfcpp::Elf_file<size, big_endian, Object>*,
|
||||
Read_symbols_data*);
|
||||
|
||||
// If NAME is the name of a special .gnu.warning section, arrange
|
||||
// for the warning to be issued. SHNDX is the section index.
|
||||
// Return whether it is a warning section.
|
||||
bool
|
||||
handle_gnu_warning_section(const char* name, unsigned int shndx,
|
||||
Symbol_table*);
|
||||
|
||||
private:
|
||||
// This class may not be copied.
|
||||
|
@ -271,6 +309,8 @@ class Object
|
|||
// Offset within the file--0 for an object file, non-0 for an
|
||||
// archive.
|
||||
off_t offset_;
|
||||
// Number of input sections.
|
||||
unsigned int shnum_;
|
||||
// Whether this is a dynamic object.
|
||||
bool is_dynamic_;
|
||||
// Target functions--may be NULL if the target is not known.
|
||||
|
@ -377,24 +417,12 @@ class Relobj : public Object
|
|||
do_relocate(const General_options& options, const Symbol_table* symtab,
|
||||
const Layout*, Output_file* of) = 0;
|
||||
|
||||
// Get the number of sections.
|
||||
unsigned int
|
||||
shnum() const
|
||||
{ return this->shnum_; }
|
||||
|
||||
// Set the number of sections.
|
||||
void
|
||||
set_shnum(int shnum)
|
||||
{ this->shnum_ = shnum; }
|
||||
|
||||
// Return the vector mapping input sections to output sections.
|
||||
std::vector<Map_to_output>&
|
||||
map_to_output()
|
||||
{ return this->map_to_output_; }
|
||||
|
||||
private:
|
||||
// Number of input sections.
|
||||
unsigned int shnum_;
|
||||
// Mapping from input sections to output section.
|
||||
std::vector<Map_to_output> map_to_output_;
|
||||
};
|
||||
|
@ -428,6 +456,11 @@ class Sized_relobj : public Relobj
|
|||
void
|
||||
do_read_symbols(Read_symbols_data*);
|
||||
|
||||
// Lay out the input sections.
|
||||
void
|
||||
do_layout(const General_options&, Symbol_table*, Layout*,
|
||||
Read_symbols_data*);
|
||||
|
||||
// Add the symbols to the symbol table.
|
||||
void
|
||||
do_add_symbols(Symbol_table*, Read_symbols_data*);
|
||||
|
@ -441,11 +474,6 @@ class Sized_relobj : public Relobj
|
|||
do_scan_relocs(const General_options&, Symbol_table*, Layout*,
|
||||
Read_relocs_data*);
|
||||
|
||||
// Lay out the input sections.
|
||||
void
|
||||
do_layout(const General_options&, Symbol_table*, Layout*,
|
||||
Read_symbols_data*);
|
||||
|
||||
// Finalize the local symbols.
|
||||
off_t
|
||||
do_finalize_local_symbols(off_t, Stringpool*);
|
||||
|
@ -461,7 +489,7 @@ class Sized_relobj : public Relobj
|
|||
{ return this->elf_file_.section_name(shndx); }
|
||||
|
||||
// Return the location of the contents of a section.
|
||||
Location
|
||||
Object::Location
|
||||
do_section_contents(unsigned int shndx)
|
||||
{ return this->elf_file_.section_contents(shndx); }
|
||||
|
||||
|
@ -482,6 +510,10 @@ class Sized_relobj : public Relobj
|
|||
static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
typedef elfcpp::Shdr<size, big_endian> Shdr;
|
||||
|
||||
// Find the SHT_SYMTAB section, given the section headers.
|
||||
void
|
||||
find_symtab(const unsigned char* pshdrs);
|
||||
|
||||
// Whether to include a section group in the link.
|
||||
bool
|
||||
include_section_group(Layout*, unsigned int,
|
||||
|
@ -520,8 +552,6 @@ class Sized_relobj : public Relobj
|
|||
|
||||
// General access to the ELF file.
|
||||
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
|
||||
// If non-NULL, a view of the section header data.
|
||||
File_view* section_headers_;
|
||||
// Index of SHT_SYMTAB section.
|
||||
unsigned int symtab_shndx_;
|
||||
// The number of local symbols.
|
||||
|
|
|
@ -231,6 +231,9 @@ options::Command_line_options::options[] =
|
|||
TWO_DASHES, &start_group),
|
||||
SPECIAL(')', "end-group", N_("End a library search group"), NULL,
|
||||
TWO_DASHES, &end_group),
|
||||
GENERAL_ARG('I', "dynamic-linker", N_("Set dynamic linker path"),
|
||||
N_("-I PROGRAM, --dynamic-linker PROGRAM"), TWO_DASHES,
|
||||
&General_options::set_dynamic_linker),
|
||||
GENERAL_ARG('L', "library-path", N_("Add directory to search path"),
|
||||
N_("-L DIR, --library-path DIR"), TWO_DASHES,
|
||||
&General_options::add_to_search_path),
|
||||
|
@ -245,6 +248,12 @@ options::Command_line_options::options[] =
|
|||
NULL, ONE_DASH, &General_options::set_shared),
|
||||
GENERAL_NOARG('\0', "static", N_("Do not link against shared libraries"),
|
||||
NULL, ONE_DASH, &General_options::set_static),
|
||||
POSDEP_NOARG('\0', "as-needed",
|
||||
N_("Only set DT_NEEDED for following dynamic libs if used"),
|
||||
NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
|
||||
POSDEP_NOARG('\0', "no-as-needed",
|
||||
N_("Always DT_NEEDED for following dynamic libs (default)"),
|
||||
NULL, TWO_DASHES, &Position_dependent_options::clear_as_needed),
|
||||
SPECIAL('\0', "help", N_("Report usage information"), NULL,
|
||||
TWO_DASHES, &help)
|
||||
};
|
||||
|
@ -255,7 +264,8 @@ const int options::Command_line_options::options_size =
|
|||
// The default values for the general options.
|
||||
|
||||
General_options::General_options()
|
||||
: search_path_(),
|
||||
: dynamic_linker_(NULL),
|
||||
search_path_(),
|
||||
output_file_name_("a.out"),
|
||||
is_relocatable_(false),
|
||||
is_shared_(false),
|
||||
|
@ -270,10 +280,47 @@ Position_dependent_options::Position_dependent_options()
|
|||
{
|
||||
}
|
||||
|
||||
// Input_arguments methods.
|
||||
|
||||
// Add a file to the list.
|
||||
|
||||
void
|
||||
Input_arguments::add_file(const Input_file_argument& file)
|
||||
{
|
||||
if (!this->in_group_)
|
||||
this->input_argument_list_.push_back(Input_argument(file));
|
||||
else
|
||||
{
|
||||
assert(!this->input_argument_list_.empty());
|
||||
assert(this->input_argument_list_.back().is_group());
|
||||
this->input_argument_list_.back().group()->add_file(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Start a group.
|
||||
|
||||
void
|
||||
Input_arguments::start_group()
|
||||
{
|
||||
assert(!this->in_group_);
|
||||
Input_file_group* group = new Input_file_group();
|
||||
this->input_argument_list_.push_back(Input_argument(group));
|
||||
this->in_group_ = true;
|
||||
}
|
||||
|
||||
// End a group.
|
||||
|
||||
void
|
||||
Input_arguments::end_group()
|
||||
{
|
||||
assert(this->in_group_);
|
||||
this->in_group_ = false;
|
||||
}
|
||||
|
||||
// Command_line options.
|
||||
|
||||
Command_line::Command_line()
|
||||
: options_(), position_options_(), inputs_(), in_group_(false)
|
||||
: options_(), position_options_(), inputs_()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -409,7 +456,7 @@ Command_line::process(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
if (this->in_group_)
|
||||
if (this->inputs_.in_group())
|
||||
{
|
||||
fprintf(stderr, _("%s: missing group end"), program_name);
|
||||
this->usage();
|
||||
|
@ -452,14 +499,7 @@ void
|
|||
Command_line::add_file(const char* name, bool is_lib)
|
||||
{
|
||||
Input_file_argument file(name, is_lib, this->position_options_);
|
||||
if (!this->in_group_)
|
||||
this->inputs_.push_back(Input_argument(file));
|
||||
else
|
||||
{
|
||||
assert(!this->inputs_.empty());
|
||||
assert(this->inputs_.back().is_group());
|
||||
this->inputs_.back().group()->add_file(file);
|
||||
}
|
||||
this->inputs_.add_file(file);
|
||||
}
|
||||
|
||||
// Handle the -l option, which requires special treatment.
|
||||
|
@ -492,14 +532,9 @@ Command_line::process_l_option(int argc, char** argv, char* arg)
|
|||
void
|
||||
Command_line::start_group(const char* arg)
|
||||
{
|
||||
if (this->in_group_)
|
||||
if (this->inputs_.in_group())
|
||||
this->usage(_("may not nest groups"), arg);
|
||||
|
||||
// This object is leaked.
|
||||
Input_file_group* group = new Input_file_group();
|
||||
this->inputs_.push_back(Input_argument(group));
|
||||
|
||||
this->in_group_ = true;
|
||||
this->inputs_.start_group();
|
||||
}
|
||||
|
||||
// Handle the --end-group option.
|
||||
|
@ -507,9 +542,9 @@ Command_line::start_group(const char* arg)
|
|||
void
|
||||
Command_line::end_group(const char* arg)
|
||||
{
|
||||
if (!this->in_group_)
|
||||
if (!this->inputs_.in_group())
|
||||
this->usage(_("group end without group start"), arg);
|
||||
this->in_group_ = false;
|
||||
this->inputs_.end_group();
|
||||
}
|
||||
|
||||
// Report a usage error. */
|
||||
|
|
100
gold/options.h
100
gold/options.h
|
@ -38,6 +38,11 @@ class General_options
|
|||
public:
|
||||
General_options();
|
||||
|
||||
// -I: dynamic linker name.
|
||||
const char*
|
||||
dynamic_linker() const
|
||||
{ return this->dynamic_linker_; }
|
||||
|
||||
// -L: Library search path.
|
||||
typedef std::list<const char*> Dir_list;
|
||||
|
||||
|
@ -66,9 +71,17 @@ class General_options
|
|||
{ return this->is_static_; }
|
||||
|
||||
private:
|
||||
// Don't copy this structure.
|
||||
General_options(const General_options&);
|
||||
General_options& operator=(const General_options&);
|
||||
|
||||
friend class Command_line;
|
||||
friend class options::Command_line_options;
|
||||
|
||||
void
|
||||
set_dynamic_linker(const char* arg)
|
||||
{ this->dynamic_linker_ = arg; }
|
||||
|
||||
void
|
||||
add_to_search_path(const char* arg)
|
||||
{ this->search_path_.push_back(arg); }
|
||||
|
@ -93,15 +106,12 @@ class General_options
|
|||
ignore(const char*)
|
||||
{ }
|
||||
|
||||
const char* dynamic_linker_;
|
||||
Dir_list search_path_;
|
||||
const char* output_file_name_;
|
||||
bool is_relocatable_;
|
||||
bool is_shared_;
|
||||
bool is_static_;
|
||||
|
||||
// Don't copy this structure.
|
||||
General_options(const General_options&);
|
||||
General_options& operator=(const General_options&);
|
||||
};
|
||||
|
||||
// The current state of the position dependent options.
|
||||
|
@ -112,14 +122,16 @@ class Position_dependent_options
|
|||
Position_dependent_options();
|
||||
|
||||
// -Bstatic: Whether we are searching for a static archive rather
|
||||
// -than a shared object.
|
||||
// than a shared object.
|
||||
bool
|
||||
do_static_search()
|
||||
do_static_search() const
|
||||
{ return this->do_static_search_; }
|
||||
|
||||
private:
|
||||
friend class Command_line;
|
||||
friend class options::Command_line_options;
|
||||
// --as-needed: Whether to add a DT_NEEDED argument only if the
|
||||
// dynamic object is used.
|
||||
bool
|
||||
as_needed() const
|
||||
{ return this->as_needed_; }
|
||||
|
||||
void
|
||||
set_static_search()
|
||||
|
@ -129,7 +141,17 @@ class Position_dependent_options
|
|||
set_dynamic_search()
|
||||
{ this->do_static_search_ = false; }
|
||||
|
||||
void
|
||||
set_as_needed()
|
||||
{ this->as_needed_ = true; }
|
||||
|
||||
void
|
||||
clear_as_needed()
|
||||
{ this->as_needed_ = false; }
|
||||
|
||||
private:
|
||||
bool do_static_search_;
|
||||
bool as_needed_;
|
||||
};
|
||||
|
||||
// A single file or library argument from the command line.
|
||||
|
@ -138,7 +160,7 @@ class Input_file_argument
|
|||
{
|
||||
public:
|
||||
Input_file_argument()
|
||||
: name_(NULL), is_lib_(false), options_()
|
||||
: name_(), is_lib_(false), options_()
|
||||
{ }
|
||||
|
||||
Input_file_argument(const char* name, bool is_lib,
|
||||
|
@ -148,7 +170,7 @@ class Input_file_argument
|
|||
|
||||
const char*
|
||||
name() const
|
||||
{ return this->name_; }
|
||||
{ return this->name_.c_str(); }
|
||||
|
||||
const Position_dependent_options&
|
||||
options() const
|
||||
|
@ -159,7 +181,10 @@ class Input_file_argument
|
|||
{ return this->is_lib_; }
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
// We use std::string, not const char*, here for convenience when
|
||||
// using script files, so that we do not have to preserve the string
|
||||
// in that case.
|
||||
std::string name_;
|
||||
bool is_lib_;
|
||||
Position_dependent_options options_;
|
||||
};
|
||||
|
@ -250,12 +275,60 @@ class Input_file_group
|
|||
Files files_;
|
||||
};
|
||||
|
||||
// A list of files from the command line or a script.
|
||||
|
||||
class Input_arguments
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Input_argument> Input_argument_list;
|
||||
typedef Input_argument_list::const_iterator const_iterator;
|
||||
|
||||
Input_arguments()
|
||||
: input_argument_list_(), in_group_(false)
|
||||
{ }
|
||||
|
||||
// Add a file.
|
||||
void
|
||||
add_file(const Input_file_argument& arg);
|
||||
|
||||
// Start a group (the --start-group option).
|
||||
void
|
||||
start_group();
|
||||
|
||||
// End a group (the --end-group option).
|
||||
void
|
||||
end_group();
|
||||
|
||||
// Return whether we are currently in a group.
|
||||
bool
|
||||
in_group() const
|
||||
{ return this->in_group_; }
|
||||
|
||||
// Iterators to iterate over the list of input files.
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{ return this->input_argument_list_.begin(); }
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{ return this->input_argument_list_.end(); }
|
||||
|
||||
// Return whether the list is empty.
|
||||
bool
|
||||
empty() const
|
||||
{ return this->input_argument_list_.empty(); }
|
||||
|
||||
private:
|
||||
Input_argument_list input_argument_list_;
|
||||
bool in_group_;
|
||||
};
|
||||
|
||||
// All the information read from the command line.
|
||||
|
||||
class Command_line
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Input_argument> Input_arguments;
|
||||
typedef Input_arguments::const_iterator const_iterator;
|
||||
|
||||
Command_line();
|
||||
|
@ -315,7 +388,6 @@ class Command_line
|
|||
General_options options_;
|
||||
Position_dependent_options position_options_;
|
||||
Input_arguments inputs_;
|
||||
bool in_group_;
|
||||
};
|
||||
|
||||
} // End namespace gold.
|
||||
|
|
|
@ -48,14 +48,6 @@ Output_data::default_alignment(int size)
|
|||
abort();
|
||||
}
|
||||
|
||||
// Output_data_const methods.
|
||||
|
||||
void
|
||||
Output_data_const::do_write(Output_file* output)
|
||||
{
|
||||
output->write(this->offset(), data_.data(), data_.size());
|
||||
}
|
||||
|
||||
// Output_section_header methods. This currently assumes that the
|
||||
// segment and section lists are complete at construction time.
|
||||
|
||||
|
@ -357,13 +349,30 @@ Output_file_header::do_sized_write(Output_file* of)
|
|||
of->write_output_view(0, ehdr_size, view);
|
||||
}
|
||||
|
||||
// Output_section_got::Got_entry methods.
|
||||
// Output_data_const methods.
|
||||
|
||||
void
|
||||
Output_data_const::do_write(Output_file* output)
|
||||
{
|
||||
output->write(this->offset(), data_.data(), data_.size());
|
||||
}
|
||||
|
||||
// Output_section_data methods.
|
||||
|
||||
unsigned int
|
||||
Output_section_data::do_out_shndx() const
|
||||
{
|
||||
assert(this->output_section_ != NULL);
|
||||
return this->output_section_->out_shndx();
|
||||
}
|
||||
|
||||
// Output_data_got::Got_entry methods.
|
||||
|
||||
// Write out the entry.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_section_got<size, big_endian>::Got_entry::write(unsigned char* pov)
|
||||
Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov)
|
||||
const
|
||||
{
|
||||
Valtype val = 0;
|
||||
|
@ -402,22 +411,30 @@ Output_section_got<size, big_endian>::Got_entry::write(unsigned char* pov)
|
|||
elfcpp::Swap<size, big_endian>::writeval(povv, val);
|
||||
}
|
||||
|
||||
// Output_section_data methods.
|
||||
// Output_data_got methods.
|
||||
|
||||
unsigned int
|
||||
Output_section_data::do_out_shndx() const
|
||||
// Add an entry for a global symbol to the GOT. This returns true if
|
||||
// this is a new GOT entry, false if the symbol already had a GOT
|
||||
// entry.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
Output_data_got<size, big_endian>::add_global(Symbol* gsym)
|
||||
{
|
||||
assert(this->output_section_ != NULL);
|
||||
return this->output_section_->out_shndx();
|
||||
}
|
||||
if (gsym->has_got_offset())
|
||||
return false;
|
||||
|
||||
// Output_section_got methods.
|
||||
this->entries_.push_back(Got_entry(gsym));
|
||||
this->set_got_size();
|
||||
gsym->set_got_offset(this->last_got_offset());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write out the GOT.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_section_got<size, big_endian>::do_write(Output_file* of)
|
||||
Output_data_got<size, big_endian>::do_write(Output_file* of)
|
||||
{
|
||||
const int add = size / 8;
|
||||
|
||||
|
@ -655,7 +672,8 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
|
|||
|
||||
void
|
||||
Output_segment::add_output_section(Output_section* os,
|
||||
elfcpp::Elf_Word seg_flags)
|
||||
elfcpp::Elf_Word seg_flags,
|
||||
bool front)
|
||||
{
|
||||
assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
|
||||
assert(!this->is_align_known_);
|
||||
|
@ -690,6 +708,7 @@ Output_segment::add_output_section(Output_section* os,
|
|||
--p;
|
||||
if ((*p)->is_section_type(elfcpp::SHT_NOTE))
|
||||
{
|
||||
// We don't worry about the FRONT parameter.
|
||||
++p;
|
||||
pdl->insert(p, os);
|
||||
return;
|
||||
|
@ -730,6 +749,7 @@ Output_segment::add_output_section(Output_section* os,
|
|||
|
||||
if (insert)
|
||||
{
|
||||
// We don't worry about the FRONT parameter.
|
||||
++p;
|
||||
pdl->insert(p, os);
|
||||
return;
|
||||
|
@ -737,11 +757,14 @@ Output_segment::add_output_section(Output_section* os,
|
|||
}
|
||||
while (p != pdl->begin());
|
||||
|
||||
// There are no TLS sections yet; put this one at the end of the
|
||||
// section list.
|
||||
// There are no TLS sections yet; put this one at the requested
|
||||
// location in the section list.
|
||||
}
|
||||
|
||||
pdl->push_back(os);
|
||||
if (front)
|
||||
pdl->push_front(os);
|
||||
else
|
||||
pdl->push_back(os);
|
||||
}
|
||||
|
||||
// Add an Output_data (which is not an Output_section) to the start of
|
||||
|
@ -1121,19 +1144,15 @@ Output_section::add_input_section<64, true>(
|
|||
const elfcpp::Shdr<64, true>& shdr);
|
||||
|
||||
template
|
||||
void
|
||||
Output_section_got<32, false>::do_write(Output_file* of);
|
||||
class Output_data_got<32, false>;
|
||||
|
||||
template
|
||||
void
|
||||
Output_section_got<32, true>::do_write(Output_file* of);
|
||||
class Output_data_got<32, true>;
|
||||
|
||||
template
|
||||
void
|
||||
Output_section_got<64, false>::do_write(Output_file* of);
|
||||
class Output_data_got<64, false>;
|
||||
|
||||
template
|
||||
void
|
||||
Output_section_got<64, true>::do_write(Output_file* of);
|
||||
class Output_data_got<64, true>;
|
||||
|
||||
} // End namespace gold.
|
||||
|
|
100
gold/output.h
100
gold/output.h
|
@ -160,34 +160,6 @@ class Output_data
|
|||
off_t offset_;
|
||||
};
|
||||
|
||||
// A simple case of Output_data in which we have constant data to
|
||||
// output.
|
||||
|
||||
class Output_data_const : public Output_data
|
||||
{
|
||||
public:
|
||||
Output_data_const(const std::string& data, uint64_t addralign)
|
||||
: Output_data(data.size()), data_(data), addralign_(addralign)
|
||||
{ }
|
||||
|
||||
Output_data_const(const char* p, off_t len, uint64_t addralign)
|
||||
: Output_data(len), data_(p, len), addralign_(addralign)
|
||||
{ }
|
||||
|
||||
// Write the data to the file.
|
||||
void
|
||||
do_write(Output_file* output);
|
||||
|
||||
// Return the required alignment.
|
||||
uint64_t
|
||||
do_addralign() const
|
||||
{ return this->addralign_; }
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
uint64_t addralign_;
|
||||
};
|
||||
|
||||
// Output the section headers.
|
||||
|
||||
class Output_section_headers : public Output_data
|
||||
|
@ -340,13 +312,40 @@ class Output_section_data : public Output_data
|
|||
uint64_t addralign_;
|
||||
};
|
||||
|
||||
// Output_section_common is used to handle the common symbols. This
|
||||
// is quite simple.
|
||||
// A simple case of Output_data in which we have constant data to
|
||||
// output.
|
||||
|
||||
class Output_section_common : public Output_section_data
|
||||
class Output_data_const : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_section_common(uint64_t addralign)
|
||||
Output_data_const(const std::string& data, uint64_t addralign)
|
||||
: Output_section_data(data.size(), addralign), data_(data)
|
||||
{ }
|
||||
|
||||
Output_data_const(const char* p, off_t len, uint64_t addralign)
|
||||
: Output_section_data(len, addralign), data_(p, len)
|
||||
{ }
|
||||
|
||||
Output_data_const(const unsigned char* p, off_t len, uint64_t addralign)
|
||||
: Output_section_data(len, addralign),
|
||||
data_(reinterpret_cast<const char*>(p), len)
|
||||
{ }
|
||||
|
||||
// Write the data to the file.
|
||||
void
|
||||
do_write(Output_file* output);
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
};
|
||||
|
||||
// Output_data_common is used to handle the common symbols. This is
|
||||
// quite simple.
|
||||
|
||||
class Output_data_common : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_data_common(uint64_t addralign)
|
||||
: Output_section_data(addralign)
|
||||
{ }
|
||||
|
||||
|
@ -362,32 +361,26 @@ class Output_section_common : public Output_section_data
|
|||
{ }
|
||||
};
|
||||
|
||||
// Output_section_got is used to manage a GOT. Each entry in the GOT
|
||||
// is for one symbol--either a global symbol or a local symbol in an
|
||||
// Output_data_got is used to manage a GOT. Each entry in the GOT is
|
||||
// for one symbol--either a global symbol or a local symbol in an
|
||||
// object. The target specific code adds entries to the GOT as
|
||||
// needed. The GOT code is then responsible for writing out the data
|
||||
// and for generating relocs as required.
|
||||
// needed.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Output_section_got : public Output_section_data
|
||||
class Output_data_got : public Output_section_data
|
||||
{
|
||||
public:
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
|
||||
|
||||
Output_section_got()
|
||||
Output_data_got()
|
||||
: Output_section_data(Output_data::default_alignment(size)),
|
||||
entries_()
|
||||
{ }
|
||||
|
||||
// Add an entry for a global symbol to the GOT. This returns the
|
||||
// offset of the new entry from the start of the GOT.
|
||||
unsigned int
|
||||
add_global(Symbol* gsym)
|
||||
{
|
||||
this->entries_.push_back(Got_entry(gsym));
|
||||
this->set_got_size();
|
||||
return this->last_got_offset();
|
||||
}
|
||||
// Add an entry for a global symbol to the GOT. Return true if this
|
||||
// is a new GOT entry, false if the symbol was already in the GOT.
|
||||
bool
|
||||
add_global(Symbol* gsym);
|
||||
|
||||
// Add an entry for a local symbol to the GOT. This returns the
|
||||
// offset of the new entry from the start of the GOT.
|
||||
|
@ -789,7 +782,13 @@ class Output_segment
|
|||
|
||||
// Add an Output_section to this segment.
|
||||
void
|
||||
add_output_section(Output_section*, elfcpp::Elf_Word seg_flags);
|
||||
add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags)
|
||||
{ this->add_output_section(os, seg_flags, false); }
|
||||
|
||||
// Add an Output_section to the start of this segment.
|
||||
void
|
||||
add_initial_output_section(Output_section* os, elfcpp::Elf_Word seg_flags)
|
||||
{ this->add_output_section(os, seg_flags, true); }
|
||||
|
||||
// Add an Output_data (which is not an Output_section) to the start
|
||||
// of this segment.
|
||||
|
@ -832,6 +831,11 @@ class Output_segment
|
|||
|
||||
typedef std::list<Output_data*> Output_data_list;
|
||||
|
||||
// Add an Output_section to this segment, specifying front or back.
|
||||
void
|
||||
add_output_section(Output_section*, elfcpp::Elf_Word seg_flags,
|
||||
bool front);
|
||||
|
||||
// Find the maximum alignment in an Output_data_list.
|
||||
static uint64_t
|
||||
maximum_alignment(const Output_data_list*);
|
||||
|
|
|
@ -6,6 +6,8 @@ defstd.cc
|
|||
defstd.h
|
||||
dirsearch.cc
|
||||
dirsearch.h
|
||||
dynobj.cc
|
||||
dynobj.h
|
||||
fileread.cc
|
||||
fileread.h
|
||||
gold.cc
|
||||
|
@ -26,6 +28,8 @@ readsyms.h
|
|||
reloc.cc
|
||||
reloc.h
|
||||
resolve.cc
|
||||
script.cc
|
||||
script.h
|
||||
stringpool.cc
|
||||
stringpool.h
|
||||
symtab.cc
|
||||
|
|
275
gold/po/gold.pot
275
gold/po/gold.pot
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-11-07 10:50-0800\n"
|
||||
"POT-Creation-Date: 2006-11-14 11:17-0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -61,6 +61,101 @@ msgstr ""
|
|||
msgid "can not read directory %s"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:97
|
||||
#, c-format
|
||||
msgid "%s: %s: unexpected duplicate type %u section: %u, %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:138
|
||||
#, c-format
|
||||
msgid "%s: %s: unexpected link in section %u header: %u != %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:176
|
||||
#, c-format
|
||||
msgid "%s: %s: DYNAMIC section %u link out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:186
|
||||
#, c-format
|
||||
msgid "%s: %s: DYNAMIC section %u link %u is not a strtab\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:208
|
||||
#, c-format
|
||||
msgid "%s: %s: DT_SONAME value out of range: %lld >= %lld\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:225
|
||||
#, c-format
|
||||
msgid "%s: %s: missing DT_NULL in dynamic segment\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:273
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid dynamic symbol table name index: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:281
|
||||
#, c-format
|
||||
msgid "%s: %s: dynamic symbol table name section has wrong type: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:356 object.cc:421
|
||||
#, c-format
|
||||
msgid "%s: %s: bad section name offset for section %u: %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:386
|
||||
#, c-format
|
||||
msgid "%s: %s: duplicate definition for version %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:430 dynobj.cc:549
|
||||
#, c-format
|
||||
msgid "%s: %s: verdef vd_next field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:454
|
||||
#, c-format
|
||||
msgid "%s: %s: verneed vn_aux field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:473
|
||||
#, c-format
|
||||
msgid "%s: %s: verneed vna_next field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:486
|
||||
#, c-format
|
||||
msgid "%s: %s: verneed vn_next field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:516
|
||||
#, c-format
|
||||
msgid "%s: %s: verdef vd_cnt field too small: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:525
|
||||
#, c-format
|
||||
msgid "%s: %s: verdef vd_aux field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:537
|
||||
#, c-format
|
||||
msgid "%s: %s: verdaux vda_name field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:579
|
||||
#, c-format
|
||||
msgid "%s: %s: vernaux vna_name field out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: dynobj.cc:615
|
||||
#, c-format
|
||||
msgid "%s: %s: size of dynamic symbols is not multiple of symbol size\n"
|
||||
msgstr ""
|
||||
|
||||
#: fileread.cc:56
|
||||
#, c-format
|
||||
msgid "%s: warning: close(%s) failed: %s"
|
||||
|
@ -145,148 +240,147 @@ msgstr ""
|
|||
msgid "%s: missing expected TLS relocation\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:306 i386.cc:434 i386.cc:627
|
||||
#: i386.cc:307 i386.cc:430 i386.cc:623
|
||||
#, c-format
|
||||
msgid "%s: %s: unexpected reloc %u in object file\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:339 i386.cc:358
|
||||
#: i386.cc:340 i386.cc:359
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported reloc %u against local symbol\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:415 i386.cc:469 i386.cc:487
|
||||
#: i386.cc:411 i386.cc:465 i386.cc:483
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported reloc %u against global symbol %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:509
|
||||
#: i386.cc:505
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported RELA reloc section\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:548
|
||||
#: i386.cc:544
|
||||
#, c-format
|
||||
msgid "%s: %s: missing expected TLS relocation\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:594 i386.cc:659 i386.cc:732 i386.cc:743
|
||||
#: i386.cc:590 i386.cc:655 i386.cc:728 i386.cc:739
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported reloc %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:686
|
||||
#: i386.cc:682
|
||||
#, c-format
|
||||
msgid "%s: %s: TLS reloc but no TLS segment\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:717
|
||||
#: i386.cc:713
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported reloc type %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:926
|
||||
#: i386.cc:922
|
||||
#, c-format
|
||||
msgid "%s: %s: TLS relocation out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: i386.cc:944
|
||||
#: i386.cc:940
|
||||
#, c-format
|
||||
msgid "%s: %s: TLS relocation against invalid instruction\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:87
|
||||
#: object.cc:31
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF machine number %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:173
|
||||
#: object.cc:87
|
||||
#, c-format
|
||||
msgid "%s: %s: section name section has wrong type: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:229
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid symbol table name index: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:181
|
||||
#: object.cc:237
|
||||
#, c-format
|
||||
msgid "%s: %s: symbol table name section has wrong type: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:237
|
||||
#: object.cc:293
|
||||
#, c-format
|
||||
msgid "%s: %s: section group %u info %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:254
|
||||
#: object.cc:310
|
||||
#, c-format
|
||||
msgid "%s: %s: symbol %u name offset %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:288
|
||||
#: object.cc:344
|
||||
#, c-format
|
||||
msgid "%s: %s: section %u in section group %u out of range"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:368
|
||||
#, c-format
|
||||
msgid "%s: %s: bad section name offset for section %u: %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:436
|
||||
#: object.cc:488
|
||||
#, c-format
|
||||
msgid "%s: %s: size of symbols is not multiple of symbol size\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:521
|
||||
#: object.cc:572
|
||||
#, c-format
|
||||
msgid "%s: %s: unknown section index %u for local symbol %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:532
|
||||
#: object.cc:583
|
||||
#, c-format
|
||||
msgid "%s: %s: local symbol %u section index %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:554
|
||||
#: object.cc:605
|
||||
#, c-format
|
||||
msgid "%s: %s: local symbol %u section name out of range: %u >= %u\n"
|
||||
msgstr ""
|
||||
|
||||
#. elfcpp::ET_DYN
|
||||
#: object.cc:731
|
||||
#: object.cc:782
|
||||
#, c-format
|
||||
msgid "%s: %s: dynamic objects are not yet supported\n"
|
||||
msgid "%s: %s: unsupported ELF file type %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:755 object.cc:808 object.cc:829
|
||||
#: object.cc:801 object.cc:854 object.cc:875
|
||||
#, c-format
|
||||
msgid "%s: %s: ELF file too short\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:764
|
||||
#: object.cc:810
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF version 0\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:767
|
||||
#: object.cc:813
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF version %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:775
|
||||
#: object.cc:821
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF class 0\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:782
|
||||
#: object.cc:828
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF class %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:790
|
||||
#: object.cc:836
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF data encoding\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:797
|
||||
#: object.cc:843
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF data encoding %d\n"
|
||||
msgstr ""
|
||||
|
@ -315,139 +409,160 @@ msgid "End a library search group"
|
|||
msgstr ""
|
||||
|
||||
#: options.cc:234
|
||||
msgid "Add directory to search path"
|
||||
msgid "Set dynamic linker path"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:235
|
||||
msgid "-L DIR, --library-path DIR"
|
||||
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:237
|
||||
msgid "Ignored for compatibility"
|
||||
msgid "Add directory to search path"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:239
|
||||
msgid "Set output file name"
|
||||
#: options.cc:238
|
||||
msgid "-L DIR, --library-path DIR"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:240
|
||||
msgid "-o FILE, --output FILE"
|
||||
msgid "Ignored for compatibility"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:242
|
||||
msgid "Set output file name"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:243
|
||||
msgid "-o FILE, --output FILE"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:245
|
||||
msgid "Generate relocatable output"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:244
|
||||
#: options.cc:247
|
||||
msgid "Generate shared library"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:246
|
||||
#: options.cc:249
|
||||
msgid "Do not link against shared libraries"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:248
|
||||
#: options.cc:252
|
||||
msgid "Only set DT_NEEDED for following dynamic libs if used"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:255
|
||||
msgid "Always DT_NEEDED for following dynamic libs (default)"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:257
|
||||
msgid "Report usage information"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:346 options.cc:397 options.cc:483
|
||||
#: options.cc:393 options.cc:444 options.cc:523
|
||||
msgid "missing argument"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:359 options.cc:406
|
||||
#: options.cc:406 options.cc:453
|
||||
msgid "unknown option"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:414
|
||||
#: options.cc:461
|
||||
#, c-format
|
||||
msgid "%s: missing group end"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:496
|
||||
#: options.cc:536
|
||||
msgid "may not nest groups"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:511
|
||||
#: options.cc:546
|
||||
msgid "group end without group start"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:521
|
||||
#: options.cc:556
|
||||
#, c-format
|
||||
msgid "%s: use the --help option for usage information\n"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:530
|
||||
#: options.cc:565 script.cc:1128
|
||||
#, c-format
|
||||
msgid "%s: %s: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: options.cc:539
|
||||
#: options.cc:574
|
||||
#, c-format
|
||||
msgid "%s: -%c: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:521
|
||||
#: output.cc:538
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1033
|
||||
#: output.cc:1056
|
||||
#, c-format
|
||||
msgid "%s: %s: open: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1042
|
||||
#: output.cc:1065
|
||||
#, c-format
|
||||
msgid "%s: %s: lseek: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1049
|
||||
#: output.cc:1072
|
||||
#, c-format
|
||||
msgid "%s: %s: write: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1059
|
||||
#: output.cc:1082
|
||||
#, c-format
|
||||
msgid "%s: %s: mmap: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1073
|
||||
#: output.cc:1096
|
||||
#, c-format
|
||||
msgid "%s: %s: munmap: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: output.cc:1081
|
||||
#: output.cc:1104
|
||||
#, c-format
|
||||
msgid "%s: %s: close: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: readsyms.cc:85
|
||||
#: readsyms.cc:93
|
||||
#, c-format
|
||||
msgid "%s: %s: ordinary object found in input group\n"
|
||||
msgstr ""
|
||||
|
||||
#: readsyms.cc:136
|
||||
#, c-format
|
||||
msgid "%s: %s: file is empty\n"
|
||||
msgstr ""
|
||||
|
||||
#. Here we have to handle any other input file types we need.
|
||||
#: readsyms.cc:129
|
||||
#: readsyms.cc:149
|
||||
#, c-format
|
||||
msgid "%s: %s: not an object or archive\n"
|
||||
msgstr ""
|
||||
|
||||
#: reloc.cc:168 reloc.cc:408
|
||||
#: reloc.cc:168 reloc.cc:409
|
||||
#, c-format
|
||||
msgid "%s: %s: relocation section %u has bad info %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: reloc.cc:187 reloc.cc:425
|
||||
#: reloc.cc:187 reloc.cc:426
|
||||
#, c-format
|
||||
msgid "%s: %s: relocation section %u uses unexpected symbol table %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: reloc.cc:203 reloc.cc:444
|
||||
#: reloc.cc:203 reloc.cc:445
|
||||
#, c-format
|
||||
msgid "%s: %s: unexpected entsize for reloc section %u: %lu != %u"
|
||||
msgstr ""
|
||||
|
||||
#: reloc.cc:214 reloc.cc:455
|
||||
#: reloc.cc:214 reloc.cc:456
|
||||
#, c-format
|
||||
msgid "%s: %s: reloc section %u size %lu uneven"
|
||||
msgstr ""
|
||||
|
@ -462,22 +577,42 @@ msgstr ""
|
|||
msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:441
|
||||
#: symtab.cc:443 symtab.cc:540
|
||||
#, c-format
|
||||
msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:458
|
||||
#: symtab.cc:460
|
||||
#, c-format
|
||||
msgid "%s: %s: bad global symbol name offset %u at %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:883 symtab.cc:1022
|
||||
#: symtab.cc:547
|
||||
#, c-format
|
||||
msgid "%s: %s: too few symbol versions\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:567
|
||||
#, c-format
|
||||
msgid "%s: %s: bad symbol name offset %u at %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:611
|
||||
#, c-format
|
||||
msgid "%s: %s: versym for symbol %zu out of range: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:619
|
||||
#, c-format
|
||||
msgid "%s: %s: versym for symbol %zu has no name: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:1010 symtab.cc:1149
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported symbol section 0x%x\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:1135
|
||||
#: symtab.cc:1262
|
||||
#, c-format
|
||||
msgid "%s: %s: warning: %s\n"
|
||||
msgstr ""
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "symtab.h"
|
||||
#include "object.h"
|
||||
#include "archive.h"
|
||||
#include "script.h"
|
||||
#include "readsyms.h"
|
||||
|
||||
namespace gold
|
||||
|
@ -30,8 +31,8 @@ Read_symbols::~Read_symbols()
|
|||
Task::Is_runnable_type
|
||||
Read_symbols::is_runnable(Workqueue*)
|
||||
{
|
||||
if (this->input_.is_file()
|
||||
&& this->input_.file().is_lib()
|
||||
if (this->input_argument_->is_file()
|
||||
&& this->input_argument_->file().is_lib()
|
||||
&& this->dirpath_.token().is_blocked())
|
||||
return IS_BLOCKED;
|
||||
|
||||
|
@ -53,14 +54,14 @@ Read_symbols::locks(Workqueue*)
|
|||
void
|
||||
Read_symbols::run(Workqueue* workqueue)
|
||||
{
|
||||
if (this->input_.is_group())
|
||||
if (this->input_argument_->is_group())
|
||||
{
|
||||
assert(this->input_group_ == NULL);
|
||||
this->do_group(workqueue);
|
||||
return;
|
||||
}
|
||||
|
||||
Input_file* input_file = new Input_file(this->input_.file());
|
||||
Input_file* input_file = new Input_file(this->input_argument_->file());
|
||||
input_file->open(this->options_, this->dirpath_);
|
||||
|
||||
// Read enough of the file to pick up the entire ELF header.
|
||||
|
@ -79,7 +80,14 @@ Read_symbols::run(Workqueue* workqueue)
|
|||
{
|
||||
// This is an ELF object.
|
||||
|
||||
if (this->input_group_ != NULL)
|
||||
Object* obj = make_elf_object(input_file->filename(),
|
||||
input_file, 0, p, bytes);
|
||||
|
||||
// We don't have a way to record a non-archive in an input
|
||||
// group. If this is an ordinary object file, we can't
|
||||
// include it more than once anyhow. If this is a dynamic
|
||||
// object, then including it a second time changes nothing.
|
||||
if (this->input_group_ != NULL && !obj->is_dynamic())
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: ordinary object found in input group\n"),
|
||||
|
@ -87,9 +95,6 @@ Read_symbols::run(Workqueue* workqueue)
|
|||
gold_exit(false);
|
||||
}
|
||||
|
||||
Object* obj = make_elf_object(this->input_.file().name(),
|
||||
input_file, 0, p, bytes);
|
||||
|
||||
Read_symbols_data* sd = new Read_symbols_data;
|
||||
obj->read_symbols(sd);
|
||||
workqueue->queue_front(new Add_symbols(this->options_,
|
||||
|
@ -111,7 +116,8 @@ Read_symbols::run(Workqueue* workqueue)
|
|||
if (memcmp(p, Archive::armag, Archive::sarmag) == 0)
|
||||
{
|
||||
// This is an archive.
|
||||
Archive* arch = new Archive(this->input_.file().name(), input_file);
|
||||
Archive* arch = new Archive(this->input_argument_->file().name(),
|
||||
input_file);
|
||||
arch->setup();
|
||||
workqueue->queue(new Add_archive_symbols(this->options_,
|
||||
this->symtab_,
|
||||
|
@ -125,6 +131,20 @@ Read_symbols::run(Workqueue* workqueue)
|
|||
}
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: file is empty\n"),
|
||||
program_name, input_file->file().filename().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
// Try to parse this file as a script.
|
||||
if (read_input_script(workqueue, this->options_, this->symtab_,
|
||||
this->layout_, this->dirpath_, this->input_objects_,
|
||||
this->input_group_, this->input_argument_, input_file,
|
||||
p, bytes, this->this_blocker_, this->next_blocker_))
|
||||
return;
|
||||
|
||||
// Here we have to handle any other input file types we need.
|
||||
fprintf(stderr, _("%s: %s: not an object or archive\n"),
|
||||
program_name, input_file->file().filename().c_str());
|
||||
|
@ -143,14 +163,14 @@ Read_symbols::do_group(Workqueue* workqueue)
|
|||
{
|
||||
Input_group* input_group = new Input_group();
|
||||
|
||||
const Input_file_group* group = this->input_.group();
|
||||
const Input_file_group* group = this->input_argument_->group();
|
||||
Task_token* this_blocker = this->this_blocker_;
|
||||
for (Input_file_group::const_iterator p = group->begin();
|
||||
p != group->end();
|
||||
++p)
|
||||
{
|
||||
const Input_argument& arg(*p);
|
||||
assert(arg.is_file());
|
||||
const Input_argument* arg = &*p;
|
||||
assert(arg->is_file());
|
||||
|
||||
Task_token* next_blocker = new Task_token();
|
||||
next_blocker->add_blocker();
|
||||
|
|
|
@ -36,10 +36,10 @@ class Read_symbols : public Task
|
|||
// symbols.
|
||||
Read_symbols(const General_options& options, Input_objects* input_objects,
|
||||
Symbol_table* symtab, Layout* layout, const Dirsearch& dirpath,
|
||||
const Input_argument& input, Input_group* input_group,
|
||||
const Input_argument* input_argument, Input_group* input_group,
|
||||
Task_token* this_blocker, Task_token* next_blocker)
|
||||
: options_(options), input_objects_(input_objects), symtab_(symtab),
|
||||
layout_(layout), dirpath_(dirpath), input_(input),
|
||||
layout_(layout), dirpath_(dirpath), input_argument_(input_argument),
|
||||
input_group_(input_group), this_blocker_(this_blocker),
|
||||
next_blocker_(next_blocker)
|
||||
{ }
|
||||
|
@ -67,7 +67,7 @@ class Read_symbols : public Task
|
|||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
const Dirsearch& dirpath_;
|
||||
const Input_argument& input_;
|
||||
const Input_argument* input_argument_;
|
||||
Input_group* input_group_;
|
||||
Task_token* this_blocker_;
|
||||
Task_token* next_blocker_;
|
||||
|
|
|
@ -227,6 +227,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
|||
}
|
||||
|
||||
// Read the local symbols.
|
||||
assert(this->symtab_shndx_ != -1U);
|
||||
if (this->symtab_shndx_ == 0 || this->local_symbol_count_ == 0)
|
||||
rd->local_symbols = NULL;
|
||||
else
|
||||
|
|
53
gold/script-c.h
Normal file
53
gold/script-c.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* script-c.h -- C interface for linker scripts in gold. */
|
||||
|
||||
/* This file exists so that both the bison parser and script.cc can
|
||||
include it, so that they can communicate back and forth. */
|
||||
|
||||
#ifndef GOLD_SCRIPT_C_H
|
||||
#define GOLD_SCRIPT_C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "yyscript.h"
|
||||
|
||||
/* The bison parser function. */
|
||||
|
||||
extern int
|
||||
yyparse(void* closure);
|
||||
|
||||
/* Called by the bison parser skeleton to return the next token. */
|
||||
|
||||
extern int
|
||||
yylex(YYSTYPE*, void* closure);
|
||||
|
||||
/* Called by the bison parser skeleton to report an error. */
|
||||
|
||||
extern void
|
||||
yyerror(void* closure, const char*);
|
||||
|
||||
/* Called by the bison parser to add a file to the link. */
|
||||
|
||||
extern void
|
||||
script_add_file(void* closure, const char*);
|
||||
|
||||
/* Called by the bison parser to start and stop a group. */
|
||||
|
||||
extern void
|
||||
script_start_group(void* closure);
|
||||
extern void
|
||||
script_end_group(void* closure);
|
||||
|
||||
/* Called by the bison parser to start and end an AS_NEEDED list. */
|
||||
|
||||
extern void
|
||||
script_start_as_needed(void* closure);
|
||||
extern void
|
||||
script_end_as_needed(void* closure);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(GOLD_SCRIPT_C_H) */
|
1188
gold/script.cc
Normal file
1188
gold/script.cc
Normal file
File diff suppressed because it is too large
Load diff
39
gold/script.h
Normal file
39
gold/script.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// script.h -- handle linker scripts for gold -*- C++ -*-
|
||||
|
||||
// We implement a subset of the original GNU ld linker script language
|
||||
// for compatibility. The goal is not to implement the entire
|
||||
// language. It is merely to implement enough to handle common uses.
|
||||
// In particular we need to handle /usr/lib/libc.so on a typical
|
||||
// GNU/Linux system, and we want to handle linker scripts used by the
|
||||
// Linux kernel build.
|
||||
|
||||
#ifndef GOLD_SCRIPT_H
|
||||
#define GOLD_SCRIPT_H
|
||||
|
||||
namespace gold
|
||||
{
|
||||
|
||||
class General_options;
|
||||
class Symbol_table;
|
||||
class Layout;
|
||||
class Input_objects;
|
||||
class Input_group;
|
||||
class Input_file;
|
||||
class Task_token;
|
||||
|
||||
// FILE was found as an argument on the command line, but was not
|
||||
// recognized as an ELF file. Try to read it as a script. We've
|
||||
// already read BYTES of data into P. Return true if the file was
|
||||
// handled. This has to handle /usr/lib/libc.so on a GNU/Linux
|
||||
// system.
|
||||
|
||||
bool
|
||||
read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*,
|
||||
const Dirsearch&, Input_objects*, Input_group*,
|
||||
const Input_argument*, Input_file*, const unsigned char* p,
|
||||
off_t bytes, Task_token* this_blocker,
|
||||
Task_token* next_blocker);
|
||||
|
||||
} // End namespace gold.
|
||||
|
||||
#endif // !defined(GOLD_SCRIPT_H)
|
213
gold/symtab.cc
213
gold/symtab.cc
|
@ -8,6 +8,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "object.h"
|
||||
#include "dynobj.h"
|
||||
#include "output.h"
|
||||
#include "target.h"
|
||||
#include "workqueue.h"
|
||||
|
@ -194,6 +195,7 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1,
|
|||
void
|
||||
Symbol_table::make_forwarder(Symbol* from, Symbol* to)
|
||||
{
|
||||
assert(from != to);
|
||||
assert(!from->is_forwarder() && !to->is_forwarder());
|
||||
this->forwarders_[from] = to;
|
||||
from->set_forwarder();
|
||||
|
@ -334,7 +336,7 @@ Symbol_table::add_from_object(Object* object,
|
|||
// NAME/NULL point to NAME/VERSION.
|
||||
insdef.first->second = ret;
|
||||
}
|
||||
else
|
||||
else if (insdef.first->second != ret)
|
||||
{
|
||||
// This is the unfortunate case where we already have
|
||||
// entries for both NAME/VERSION and NAME/NULL.
|
||||
|
@ -424,8 +426,8 @@ Symbol_table::add_from_object(Object* object,
|
|||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Symbol_table::add_from_object(
|
||||
Relobj* object,
|
||||
Symbol_table::add_from_relobj(
|
||||
Sized_relobj<size, big_endian>* relobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
|
@ -436,10 +438,10 @@ Symbol_table::add_from_object(
|
|||
if (this->get_size() == 0)
|
||||
this->set_size(size);
|
||||
|
||||
if (size != this->get_size() || size != object->target()->get_size())
|
||||
if (size != this->get_size() || size != relobj->target()->get_size())
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
|
||||
program_name, object->name().c_str());
|
||||
program_name, relobj->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
|
@ -456,11 +458,13 @@ Symbol_table::add_from_object(
|
|||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: bad global symbol name offset %u at %lu\n"),
|
||||
program_name, object->name().c_str(), st_name,
|
||||
program_name, relobj->name().c_str(), st_name,
|
||||
static_cast<unsigned long>(i));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const char* name = sym_names + st_name;
|
||||
|
||||
// A symbol defined in a section which we are not including must
|
||||
// be treated as an undefined symbol.
|
||||
unsigned char symbuf[sym_size];
|
||||
|
@ -468,7 +472,7 @@ Symbol_table::add_from_object(
|
|||
unsigned int st_shndx = psym->get_st_shndx();
|
||||
if (st_shndx != elfcpp::SHN_UNDEF
|
||||
&& st_shndx < elfcpp::SHN_LORESERVE
|
||||
&& !object->is_section_included(st_shndx))
|
||||
&& !relobj->is_section_included(st_shndx))
|
||||
{
|
||||
memcpy(symbuf, p, sym_size);
|
||||
elfcpp::Sym_write<size, big_endian> sw(symbuf);
|
||||
|
@ -476,8 +480,6 @@ Symbol_table::add_from_object(
|
|||
psym = &sym2;
|
||||
}
|
||||
|
||||
const char* name = sym_names + st_name;
|
||||
|
||||
// In an object file, an '@' in the name separates the symbol
|
||||
// name from the version name. If there are two '@' characters,
|
||||
// this is the default version.
|
||||
|
@ -488,7 +490,7 @@ Symbol_table::add_from_object(
|
|||
{
|
||||
Stringpool::Key name_key;
|
||||
name = this->namepool_.add(name, &name_key);
|
||||
res = this->add_from_object(object, name, name_key, NULL, 0,
|
||||
res = this->add_from_object(relobj, name, name_key, NULL, 0,
|
||||
false, *psym);
|
||||
}
|
||||
else
|
||||
|
@ -507,7 +509,7 @@ Symbol_table::add_from_object(
|
|||
Stringpool::Key ver_key;
|
||||
ver = this->namepool_.add(ver, &ver_key);
|
||||
|
||||
res = this->add_from_object(object, name, name_key, ver, ver_key,
|
||||
res = this->add_from_object(relobj, name, name_key, ver, ver_key,
|
||||
def, *psym);
|
||||
}
|
||||
|
||||
|
@ -515,6 +517,131 @@ Symbol_table::add_from_object(
|
|||
}
|
||||
}
|
||||
|
||||
// Add all the symbols in a dynamic object to the hash table.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Symbol_table::add_from_dynobj(
|
||||
Sized_dynobj<size, big_endian>* dynobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
const unsigned char* versym,
|
||||
size_t versym_size,
|
||||
const std::vector<const char*>* version_map)
|
||||
{
|
||||
// We take the size from the first object we see.
|
||||
if (this->get_size() == 0)
|
||||
this->set_size(size);
|
||||
|
||||
if (size != this->get_size() || size != dynobj->target()->get_size())
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
|
||||
program_name, dynobj->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
if (versym != NULL && versym_size / 2 < count)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: too few symbol versions\n"),
|
||||
program_name, dynobj->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
|
||||
const unsigned char* p = syms;
|
||||
const unsigned char* vs = versym;
|
||||
for (size_t i = 0; i < count; ++i, p += sym_size, vs += 2)
|
||||
{
|
||||
elfcpp::Sym<size, big_endian> sym(p);
|
||||
|
||||
// Ignore symbols with local binding.
|
||||
if (sym.get_st_bind() == elfcpp::STB_LOCAL)
|
||||
continue;
|
||||
|
||||
unsigned int st_name = sym.get_st_name();
|
||||
if (st_name >= sym_name_size)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: bad symbol name offset %u at %lu\n"),
|
||||
program_name, dynobj->name().c_str(), st_name,
|
||||
static_cast<unsigned long>(i));
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const char* name = sym_names + st_name;
|
||||
|
||||
if (versym == NULL)
|
||||
{
|
||||
Stringpool::Key name_key;
|
||||
name = this->namepool_.add(name, &name_key);
|
||||
this->add_from_object(dynobj, name, name_key, NULL, 0,
|
||||
false, sym);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the version information.
|
||||
|
||||
unsigned int v = elfcpp::Swap<16, big_endian>::readval(vs);
|
||||
|
||||
bool hidden = (v & elfcpp::VERSYM_HIDDEN) != 0;
|
||||
v &= elfcpp::VERSYM_VERSION;
|
||||
|
||||
if (v == static_cast<unsigned int>(elfcpp::VER_NDX_LOCAL))
|
||||
{
|
||||
// This symbol should not be visible outside the object.
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point we are definitely going to add this symbol.
|
||||
Stringpool::Key name_key;
|
||||
name = this->namepool_.add(name, &name_key);
|
||||
|
||||
if (v == static_cast<unsigned int>(elfcpp::VER_NDX_GLOBAL))
|
||||
{
|
||||
// This symbol does not have a version.
|
||||
this->add_from_object(dynobj, name, name_key, NULL, 0, false, sym);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v >= version_map->size())
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: %s: versym for symbol %zu out of range: %u\n"),
|
||||
program_name, dynobj->name().c_str(), i, v);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
const char* version = (*version_map)[v];
|
||||
if (version == NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s: versym for symbol %zu has no name: %u\n"),
|
||||
program_name, dynobj->name().c_str(), i, v);
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
Stringpool::Key version_key;
|
||||
version = this->namepool_.add(version, &version_key);
|
||||
|
||||
// If this is an absolute symbol, and the version name and
|
||||
// symbol name are the same, then this is the version definition
|
||||
// symbol. These symbols exist to support using -u to pull in
|
||||
// particular versions. We do not want to record a version for
|
||||
// them.
|
||||
if (sym.get_st_shndx() == elfcpp::SHN_ABS && name_key == version_key)
|
||||
{
|
||||
this->add_from_object(dynobj, name, name_key, NULL, 0, false, sym);
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool def = !hidden && sym.get_st_shndx() != elfcpp::SHN_UNDEF;
|
||||
|
||||
this->add_from_object(dynobj, name, name_key, version, version_key,
|
||||
def, sym);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and return a specially defined symbol. If ONLY_IF_REF is
|
||||
// true, then only create the symbol if there is a reference to it.
|
||||
|
||||
|
@ -1142,8 +1269,8 @@ Warnings::issue_warning(Symbol* sym, const std::string& location) const
|
|||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<32, true>(
|
||||
Relobj* object,
|
||||
Symbol_table::add_from_relobj<32, true>(
|
||||
Sized_relobj<32, true>* relobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
|
@ -1152,8 +1279,8 @@ Symbol_table::add_from_object<32, true>(
|
|||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<32, false>(
|
||||
Relobj* object,
|
||||
Symbol_table::add_from_relobj<32, false>(
|
||||
Sized_relobj<32, false>* relobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
|
@ -1162,8 +1289,8 @@ Symbol_table::add_from_object<32, false>(
|
|||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<64, true>(
|
||||
Relobj* object,
|
||||
Symbol_table::add_from_relobj<64, true>(
|
||||
Sized_relobj<64, true>* relobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
|
@ -1172,12 +1299,60 @@ Symbol_table::add_from_object<64, true>(
|
|||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<64, false>(
|
||||
Relobj* object,
|
||||
Symbol_table::add_from_relobj<64, false>(
|
||||
Sized_relobj<64, false>* relobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
Symbol** sympointers);
|
||||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_dynobj<32, true>(
|
||||
Sized_dynobj<32, true>* dynobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
const unsigned char* versym,
|
||||
size_t versym_size,
|
||||
const std::vector<const char*>* version_map);
|
||||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_dynobj<32, false>(
|
||||
Sized_dynobj<32, false>* dynobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
const unsigned char* versym,
|
||||
size_t versym_size,
|
||||
const std::vector<const char*>* version_map);
|
||||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_dynobj<64, true>(
|
||||
Sized_dynobj<64, true>* dynobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
const unsigned char* versym,
|
||||
size_t versym_size,
|
||||
const std::vector<const char*>* version_map);
|
||||
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_dynobj<64, false>(
|
||||
Sized_dynobj<64, false>* dynobj,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
const unsigned char* versym,
|
||||
size_t versym_size,
|
||||
const std::vector<const char*>* version_map);
|
||||
|
||||
} // End namespace gold.
|
||||
|
|
|
@ -20,7 +20,11 @@ namespace gold
|
|||
|
||||
class Object;
|
||||
class Relobj;
|
||||
template<int size, bool big_endian>
|
||||
class Sized_relobj;
|
||||
class Dynobj;
|
||||
template<int size, bool big_endian>
|
||||
class Sized_dynobj;
|
||||
class Output_data;
|
||||
class Output_segment;
|
||||
class Output_file;
|
||||
|
@ -592,16 +596,29 @@ class Symbol_table
|
|||
|
||||
~Symbol_table();
|
||||
|
||||
// Add COUNT external symbols from the relocatable object OBJECT to
|
||||
// Add COUNT external symbols from the relocatable object RELOBJ to
|
||||
// the symbol table. SYMS is the symbols, SYM_NAMES is their names,
|
||||
// SYM_NAME_SIZE is the size of SYM_NAMES. This sets SYMPOINTERS to
|
||||
// point to the symbols in the symbol table.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
add_from_object(Relobj* object, const unsigned char* syms,
|
||||
size_t count, const char* sym_names, size_t sym_name_size,
|
||||
add_from_relobj(Sized_relobj<size, big_endian>* relobj,
|
||||
const unsigned char* syms, size_t count,
|
||||
const char* sym_names, size_t sym_name_size,
|
||||
Symbol** sympointers);
|
||||
|
||||
// Add COUNT dynamic symbols from the dynamic object DYNOBJ to the
|
||||
// symbol table. SYMS is the symbols. SYM_NAMES is their names.
|
||||
// SYM_NAME_SIZE is the size of SYM_NAMES. The other parameters are
|
||||
// symbol version data.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
add_from_dynobj(Sized_dynobj<size, big_endian>* dynobj,
|
||||
const unsigned char* syms, size_t count,
|
||||
const char* sym_names, size_t sym_name_size,
|
||||
const unsigned char* versym, size_t versym_size,
|
||||
const std::vector<const char*>*);
|
||||
|
||||
// Define a special symbol.
|
||||
template<int size, bool big_endian>
|
||||
Sized_symbol<size>*
|
||||
|
|
|
@ -65,6 +65,11 @@ class Target
|
|||
has_resolve() const
|
||||
{ return this->pti_->has_resolve; }
|
||||
|
||||
// Return the default name of the dynamic linker.
|
||||
const char*
|
||||
dynamic_linker() const
|
||||
{ return this->pti_->dynamic_linker; }
|
||||
|
||||
// Return the default address to use for the text segment.
|
||||
uint64_t
|
||||
text_segment_address() const
|
||||
|
@ -96,6 +101,8 @@ class Target
|
|||
bool has_make_symbol;
|
||||
// Whether this target has a specific resolve function.
|
||||
bool has_resolve;
|
||||
// The default dynamic linker name.
|
||||
const char* dynamic_linker;
|
||||
// The default text segment address.
|
||||
uint64_t text_segment_address;
|
||||
// The ABI specified page size.
|
||||
|
|
168
gold/yyscript.y
Normal file
168
gold/yyscript.y
Normal file
|
@ -0,0 +1,168 @@
|
|||
/* yyscript.y -- linker script grammer for gold. */
|
||||
|
||||
/* This is a bison grammar to parse a subset of the original GNU ld
|
||||
linker script language. */
|
||||
|
||||
%{
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "script-c.h"
|
||||
|
||||
%}
|
||||
|
||||
/* We need to use a pure parser because we might be multi-threaded.
|
||||
We pass some arguments through the parser to the lexer. */
|
||||
|
||||
%pure-parser
|
||||
|
||||
%parse-param {void* closure}
|
||||
%lex-param {void* closure}
|
||||
|
||||
/* Since we require bison anyhow, we take advantage of it. */
|
||||
|
||||
%error-verbose
|
||||
|
||||
/* The values associated with tokens. */
|
||||
|
||||
%union {
|
||||
const char* string;
|
||||
int64_t integer;
|
||||
}
|
||||
|
||||
/* Operators, including a precedence table for expressions. */
|
||||
|
||||
%right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
|
||||
%right '?' ':'
|
||||
%left OROR
|
||||
%left ANDAND
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
%left EQ NE
|
||||
%left '<' '>' LE GE
|
||||
%left LSHIFT RSHIFT
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
|
||||
/* Constants. */
|
||||
|
||||
%token <string> STRING
|
||||
%token <integer> INTEGER
|
||||
|
||||
/* Keywords. This list is taken from ldgram.y and ldlex.l in the old
|
||||
GNU linker, with the keywords which only appear in MRI mode
|
||||
removed. Not all these keywords are actually used in this grammar.
|
||||
In most cases the keyword is recognized as the token name in upper
|
||||
case. The comments indicate where this is not the case. */
|
||||
|
||||
%token ABSOLUTE
|
||||
%token ADDR
|
||||
%token ALIGN_K /* ALIGN */
|
||||
%token ASSERT_K /* ASSERT */
|
||||
%token AS_NEEDED
|
||||
%token AT
|
||||
%token BIND
|
||||
%token BLOCK
|
||||
%token BYTE
|
||||
%token CONSTANT
|
||||
%token CONSTRUCTORS
|
||||
%token COPY
|
||||
%token CREATE_OBJECT_SYMBOLS
|
||||
%token DATA_SEGMENT_ALIGN
|
||||
%token DATA_SEGMENT_END
|
||||
%token DATA_SEGMENT_RELRO_END
|
||||
%token DEFINED
|
||||
%token DSECT
|
||||
%token ENTRY
|
||||
%token EXCLUDE_FILE
|
||||
%token EXTERN
|
||||
%token FILL
|
||||
%token FLOAT
|
||||
%token FORCE_COMMON_ALLOCATION
|
||||
%token GLOBAL /* global */
|
||||
%token GROUP
|
||||
%token HLL
|
||||
%token INCLUDE
|
||||
%token INFO
|
||||
%token INHIBIT_COMMON_ALLOCATION
|
||||
%token INPUT
|
||||
%token KEEP
|
||||
%token LENGTH /* LENGTH, l, len */
|
||||
%token LOADADDR
|
||||
%token LOCAL /* local */
|
||||
%token LONG
|
||||
%token MAP
|
||||
%token MAX_K /* MAX */
|
||||
%token MEMORY
|
||||
%token MIN_K /* MIN */
|
||||
%token NEXT
|
||||
%token NOCROSSREFS
|
||||
%token NOFLOAT
|
||||
%token NOLOAD
|
||||
%token ONLY_IF_RO
|
||||
%token ONLY_IF_RW
|
||||
%token ORIGIN /* ORIGIN, o, org */
|
||||
%token OUTPUT
|
||||
%token OUTPUT_ARCH
|
||||
%token OUTPUT_FORMAT
|
||||
%token OVERLAY
|
||||
%token PHDRS
|
||||
%token PROVIDE
|
||||
%token PROVIDE_HIDDEN
|
||||
%token QUAD
|
||||
%token SEARCH_DIR
|
||||
%token SECTIONS
|
||||
%token SEGMENT_START
|
||||
%token SHORT
|
||||
%token SIZEOF
|
||||
%token SIZEOF_HEADERS /* SIZEOF_HEADERS, sizeof_headers */
|
||||
%token SORT_BY_ALIGNMENT
|
||||
%token SORT_BY_NAME
|
||||
%token SPECIAL
|
||||
%token SQUAD
|
||||
%token STARTUP
|
||||
%token SUBALIGN
|
||||
%token SYSLIB
|
||||
%token TARGET_K /* TARGET */
|
||||
%token TRUNCATE
|
||||
%token VERSIONK /* VERSION */
|
||||
|
||||
%%
|
||||
|
||||
file_list:
|
||||
file_list file_cmd
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
file_cmd:
|
||||
OUTPUT_FORMAT '(' STRING ')'
|
||||
| GROUP
|
||||
{ script_start_group(closure); }
|
||||
'(' input_list ')'
|
||||
{ script_end_group(closure); }
|
||||
;
|
||||
|
||||
input_list:
|
||||
input_list_element
|
||||
| input_list opt_comma input_list_element
|
||||
;
|
||||
|
||||
input_list_element:
|
||||
STRING
|
||||
{ script_add_file(closure, $1); }
|
||||
| AS_NEEDED
|
||||
{ script_start_as_needed(closure); }
|
||||
'(' input_list ')'
|
||||
{ script_end_as_needed(closure); }
|
||||
;
|
||||
|
||||
opt_comma:
|
||||
','
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
%%
|
Loading…
Add table
Reference in a new issue