More dynamic object support, initial scripting support.

This commit is contained in:
Ian Lance Taylor 2006-11-14 19:21:05 +00:00
parent 6c73cbb1d9
commit dbe717effb
31 changed files with 3698 additions and 373 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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
View File

@ -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

View File

@ -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
View 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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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())

View File

@ -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 }

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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. */

View File

@ -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.

View File

@ -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.

View File

@ -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*);

View File

@ -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

View File

@ -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 ""

View File

@ -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();

View File

@ -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_;

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

39
gold/script.h Normal file
View 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)

View File

@ -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.

View File

@ -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>*

View File

@ -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
View 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 */
;
%%