2009-03-23 Ian Lance Taylor <iant@google.com>
* freebsd.h: New file. * i386.cc: Include "freebsd.h". (Target_i386): Derive from Target_freebsd rather than Sized_target. (Target_selector_i386): Derive from Target_selector_freebsd rather than Target_selector. * x86_64.cc: Include "freebsd.h". (Target_x86_64): Derive from Target_freebsd rather than Sized_target. (Target_selector_x86_64): Derive from Target_selector_freebsd rather than Target_selector. * target.h (class Target): Add adjust_elf_header and do_adjust_elf_header. * output.cc (Output_file_header:: do_sized_write): Call target adjust_elf_header routine. * configure.tgt: Set targ_osabi. * configure.ac: Define GOLD_DEFAULT_OSABI. * parameters.cc (Parameters::default_target): Pass GOLD_DEFAULT_OSABI to select_target. * target-select.h (class Target_selector): Make instantiate_target protected rather than private. * Makefile.am (HFILES): Add freebsd.h. * configure, Makefile.in, config.in: Rebuild.
This commit is contained in:
parent
d739bf0069
commit
3695968186
14 changed files with 259 additions and 16 deletions
|
@ -1,5 +1,29 @@
|
|||
2009-03-23 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* freebsd.h: New file.
|
||||
* i386.cc: Include "freebsd.h".
|
||||
(Target_i386): Derive from Target_freebsd rather than
|
||||
Sized_target.
|
||||
(Target_selector_i386): Derive from Target_selector_freebsd rather
|
||||
than Target_selector.
|
||||
* x86_64.cc: Include "freebsd.h".
|
||||
(Target_x86_64): Derive from Target_freebsd rather than
|
||||
Sized_target.
|
||||
(Target_selector_x86_64): Derive from Target_selector_freebsd
|
||||
rather than Target_selector.
|
||||
* target.h (class Target): Add adjust_elf_header and
|
||||
do_adjust_elf_header.
|
||||
* output.cc (Output_file_header:: do_sized_write): Call target
|
||||
adjust_elf_header routine.
|
||||
* configure.tgt: Set targ_osabi.
|
||||
* configure.ac: Define GOLD_DEFAULT_OSABI.
|
||||
* parameters.cc (Parameters::default_target): Pass
|
||||
GOLD_DEFAULT_OSABI to select_target.
|
||||
* target-select.h (class Target_selector): Make instantiate_target
|
||||
protected rather than private.
|
||||
* Makefile.am (HFILES): Add freebsd.h.
|
||||
* configure, Makefile.in, config.in: Rebuild.
|
||||
|
||||
* merge.cc (do_add_input_section): Correct pend value. Change
|
||||
message about last entry not being null terminated from error to
|
||||
warning.
|
||||
|
|
|
@ -88,6 +88,7 @@ HFILES = \
|
|||
ehframe.h \
|
||||
errors.h \
|
||||
fileread.h \
|
||||
freebsd.h \
|
||||
gc.h \
|
||||
gold.h \
|
||||
gold-threads.h \
|
||||
|
|
|
@ -371,6 +371,7 @@ HFILES = \
|
|||
ehframe.h \
|
||||
errors.h \
|
||||
fileread.h \
|
||||
freebsd.h \
|
||||
gc.h \
|
||||
gold.h \
|
||||
gold-threads.h \
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
/* Default machine code */
|
||||
#undef GOLD_DEFAULT_MACHINE
|
||||
|
||||
/* Default OSABI code */
|
||||
#undef GOLD_DEFAULT_OSABI
|
||||
|
||||
/* Default size (32 or 64) */
|
||||
#undef GOLD_DEFAULT_SIZE
|
||||
|
||||
|
|
7
gold/configure
vendored
7
gold/configure
vendored
|
@ -2030,6 +2030,7 @@ all_targets=
|
|||
default_machine=
|
||||
default_size=
|
||||
default_big_endian=
|
||||
default_osabi=ELFOSABI_NONE
|
||||
targ_32_little=
|
||||
targ_32_big=
|
||||
targ_64_little=
|
||||
|
@ -2078,6 +2079,7 @@ echo "$as_me: error: \"unsupported target $targ\"" >&2;}
|
|||
default_machine=$targ_machine
|
||||
default_size=$targ_size
|
||||
default_big_endian=$targ_big_endian
|
||||
default_osabi=$targ_osabi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
@ -2135,6 +2137,11 @@ cat >>confdefs.h <<_ACEOF
|
|||
_ACEOF
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define GOLD_DEFAULT_OSABI $default_osabi
|
||||
_ACEOF
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
|
|
|
@ -103,6 +103,7 @@ all_targets=
|
|||
default_machine=
|
||||
default_size=
|
||||
default_big_endian=
|
||||
default_osabi=ELFOSABI_NONE
|
||||
targ_32_little=
|
||||
targ_32_big=
|
||||
targ_64_little=
|
||||
|
@ -149,6 +150,7 @@ for targ in $target $canon_targets; do
|
|||
default_machine=$targ_machine
|
||||
default_size=$targ_size
|
||||
default_big_endian=$targ_big_endian
|
||||
default_osabi=$targ_osabi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
@ -184,6 +186,8 @@ AC_DEFINE_UNQUOTED(GOLD_DEFAULT_SIZE, $default_size,
|
|||
[Default size (32 or 64)])
|
||||
AC_DEFINE_UNQUOTED(GOLD_DEFAULT_BIG_ENDIAN, $default_big_endian,
|
||||
[Default big endian (true or false)])
|
||||
AC_DEFINE_UNQUOTED(GOLD_DEFAULT_OSABI, $default_osabi,
|
||||
[Default OSABI code])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# configure.tgt -- target configuration for gold -*- sh -*-
|
||||
|
||||
# Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
# Written by Ian Lance Taylor <iant@google.com>.
|
||||
|
||||
# This file is part of gold.
|
||||
|
@ -36,6 +36,7 @@
|
|||
# targ_extra_size extra targ_size setting for the target
|
||||
# targ_big_endian whether the target is big-endian--true or false
|
||||
# targ_extra_big_endian extra targ_big_endian setting for the target
|
||||
# targ_osabi EI_OSABI value
|
||||
|
||||
# If the target is not recognized targ_obj is set to "UNKNOWN".
|
||||
|
||||
|
@ -45,12 +46,18 @@ targ_size=
|
|||
targ_extra_size=
|
||||
targ_big_endian=
|
||||
targ_extra_big_endian=
|
||||
targ_osabi=ELFOSABI_NONE
|
||||
case "$targ" in
|
||||
i?86-*)
|
||||
targ_obj=i386
|
||||
targ_machine=EM_386
|
||||
targ_size=32
|
||||
targ_big_endian=false
|
||||
case "$targ" in
|
||||
i?86-*-freebsd*)
|
||||
targ_osabi=ELFOSABI_FREEBSD
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
x86_64*)
|
||||
targ_obj=x86_64
|
||||
|
@ -59,6 +66,11 @@ x86_64*)
|
|||
targ_size=64
|
||||
targ_extra_size=32
|
||||
targ_big_endian=false
|
||||
case "$targ" in
|
||||
x86_64-*-freebsd*)
|
||||
targ_osabi=ELFOSABI_FREEBSD
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sparc-*)
|
||||
targ_obj=sparc
|
||||
|
|
168
gold/freebsd.h
Normal file
168
gold/freebsd.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
// freebsd.h -- FreeBSD support for gold -*- C++ -*-
|
||||
|
||||
// Copyright 2009 Free Software Foundation, Inc.
|
||||
// Written by Ian Lance Taylor <iant@google.com>.
|
||||
|
||||
// This file is part of gold.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
|
||||
#include "target.h"
|
||||
#include "target-select.h"
|
||||
|
||||
#ifndef GOLD_FREEBSD_H
|
||||
#define GOLD_FREEBSD_H
|
||||
|
||||
namespace gold
|
||||
{
|
||||
|
||||
// FreeBSD 4.1 and later wants the EI_OSABI field in the ELF header to
|
||||
// be set to ELFOSABI_FREEBSD. This is a subclass of Sized_target
|
||||
// which supports that. The real target would be a subclass of this
|
||||
// one. We permit combining FreeBSD and non-FreeBSD object files.
|
||||
// The effect of this target is to set the code in the output file.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Target_freebsd : public Sized_target<size, big_endian>
|
||||
{
|
||||
public:
|
||||
// Set the value to use for the EI_OSABI field in the ELF header.
|
||||
void
|
||||
set_osabi(elfcpp::ELFOSABI osabi)
|
||||
{ this->osabi_ = osabi; }
|
||||
|
||||
protected:
|
||||
Target_freebsd(const Target::Target_info* pti)
|
||||
: Sized_target<size, big_endian>(pti),
|
||||
osabi_(elfcpp::ELFOSABI_NONE)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
do_adjust_elf_header(unsigned char* view, int len) const;
|
||||
|
||||
private:
|
||||
// Value to store in the EI_OSABI field of the ELF file header.
|
||||
elfcpp::ELFOSABI osabi_;
|
||||
};
|
||||
|
||||
// Adjust the ELF file header by storing the requested value in the
|
||||
// OSABI field. This is for FreeBSD support.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
inline void
|
||||
Target_freebsd<size, big_endian>::do_adjust_elf_header(unsigned char* view,
|
||||
int len) const
|
||||
{
|
||||
if (this->osabi_ != elfcpp::ELFOSABI_NONE)
|
||||
{
|
||||
gold_assert(len == elfcpp::Elf_sizes<32>::ehdr_size);
|
||||
|
||||
elfcpp::Ehdr<32, false> ehdr(view);
|
||||
unsigned char e_ident[elfcpp::EI_NIDENT];
|
||||
memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT);
|
||||
|
||||
e_ident[elfcpp::EI_OSABI] = this->osabi_;
|
||||
|
||||
elfcpp::Ehdr_write<32, false> oehdr(view);
|
||||
oehdr.put_e_ident(e_ident);
|
||||
}
|
||||
}
|
||||
|
||||
// A target selector for targets which permit combining both FreeBSD
|
||||
// and non-FreeBSD object files.
|
||||
|
||||
class Target_selector_freebsd : public Target_selector
|
||||
{
|
||||
public:
|
||||
Target_selector_freebsd(int machine, int size, bool is_big_endian,
|
||||
const char* bfd_name,
|
||||
const char* freebsd_bfd_name)
|
||||
: Target_selector(machine, size, is_big_endian, NULL),
|
||||
bfd_name_(bfd_name), freebsd_bfd_name_(freebsd_bfd_name)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
// If we see a FreeBSD input file, mark the output file as using
|
||||
// FreeBSD.
|
||||
virtual Target*
|
||||
do_recognize(int, int osabi, int)
|
||||
{
|
||||
Target* ret = this->instantiate_target();
|
||||
if (osabi == elfcpp::ELFOSABI_FREEBSD)
|
||||
this->set_osabi(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Recognize two names.
|
||||
virtual Target*
|
||||
do_recognize_by_name(const char* name)
|
||||
{
|
||||
if (strcmp(name, this->bfd_name_) == 0)
|
||||
return this->instantiate_target();
|
||||
else if (strcmp(name, this->freebsd_bfd_name_) == 0)
|
||||
{
|
||||
Target* ret = this->instantiate_target();
|
||||
this->set_osabi(ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Print both names in --help output.
|
||||
virtual void
|
||||
do_supported_names(std::vector<const char*>* names)
|
||||
{
|
||||
names->push_back(this->bfd_name_);
|
||||
names->push_back(this->freebsd_bfd_name_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Set the OSABI field. This is quite ugly.
|
||||
void
|
||||
set_osabi(Target* target)
|
||||
{
|
||||
if (this->get_size() == 32)
|
||||
{
|
||||
if (this->is_big_endian())
|
||||
static_cast<Target_freebsd<32, true>*>(target)->
|
||||
set_osabi(elfcpp::ELFOSABI_FREEBSD);
|
||||
else
|
||||
static_cast<Target_freebsd<32, false>*>(target)->
|
||||
set_osabi(elfcpp::ELFOSABI_FREEBSD);
|
||||
}
|
||||
else if (this->get_size() == 64)
|
||||
{
|
||||
if (this->is_big_endian())
|
||||
static_cast<Target_freebsd<64, true>*>(target)->
|
||||
set_osabi(elfcpp::ELFOSABI_FREEBSD);
|
||||
else
|
||||
static_cast<Target_freebsd<64, false>*>(target)->
|
||||
set_osabi(elfcpp::ELFOSABI_FREEBSD);
|
||||
}
|
||||
else
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// The BFD name for the non-Freebsd target.
|
||||
const char* bfd_name_;
|
||||
// The BFD name for the Freebsd target.
|
||||
const char* freebsd_bfd_name_;
|
||||
};
|
||||
|
||||
} // end namespace gold
|
||||
|
||||
#endif // !defined(GOLD_FREEBSD_H)
|
10
gold/i386.cc
10
gold/i386.cc
|
@ -37,6 +37,7 @@
|
|||
#include "target-reloc.h"
|
||||
#include "target-select.h"
|
||||
#include "tls.h"
|
||||
#include "freebsd.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -50,13 +51,13 @@ class Output_data_plt_i386;
|
|||
// http://people.redhat.com/drepper/tls.pdf
|
||||
// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt
|
||||
|
||||
class Target_i386 : public Sized_target<32, false>
|
||||
class Target_i386 : public Target_freebsd<32, false>
|
||||
{
|
||||
public:
|
||||
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
|
||||
|
||||
Target_i386()
|
||||
: Sized_target<32, false>(&i386_info),
|
||||
: Target_freebsd<32, false>(&i386_info),
|
||||
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
|
||||
copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
|
||||
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
|
||||
|
@ -2659,11 +2660,12 @@ Target_i386::do_code_fill(section_size_type length) const
|
|||
|
||||
// The selector for i386 object files.
|
||||
|
||||
class Target_selector_i386 : public Target_selector
|
||||
class Target_selector_i386 : public Target_selector_freebsd
|
||||
{
|
||||
public:
|
||||
Target_selector_i386()
|
||||
: Target_selector(elfcpp::EM_386, 32, false, "elf32-i386")
|
||||
: Target_selector_freebsd(elfcpp::EM_386, 32, false,
|
||||
"elf32-i386", "elf32-i386-freebsd")
|
||||
{ }
|
||||
|
||||
Target*
|
||||
|
|
|
@ -432,7 +432,6 @@ Output_file_header::do_sized_write(Output_file* of)
|
|||
? elfcpp::ELFDATA2MSB
|
||||
: elfcpp::ELFDATA2LSB);
|
||||
e_ident[elfcpp::EI_VERSION] = elfcpp::EV_CURRENT;
|
||||
// FIXME: Some targets may need to set EI_OSABI and EI_ABIVERSION.
|
||||
oehdr.put_e_ident(e_ident);
|
||||
|
||||
elfcpp::ET e_type;
|
||||
|
@ -489,6 +488,10 @@ Output_file_header::do_sized_write(Output_file* of)
|
|||
else
|
||||
oehdr.put_e_shstrndx(elfcpp::SHN_XINDEX);
|
||||
|
||||
// Let the target adjust the ELF header, e.g., to set EI_OSABI in
|
||||
// the e_ident field.
|
||||
parameters->target().adjust_elf_header(view, ehdr_size);
|
||||
|
||||
of->write_output_view(0, ehdr_size, view);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,8 @@ Parameters::default_target() const
|
|||
const Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
|
||||
GOLD_DEFAULT_SIZE,
|
||||
GOLD_DEFAULT_BIG_ENDIAN,
|
||||
0, 0);
|
||||
elfcpp::GOLD_DEFAULT_OSABI,
|
||||
0);
|
||||
gold_assert(target != NULL);
|
||||
return *target;
|
||||
}
|
||||
|
|
|
@ -106,10 +106,10 @@ class Target_selector
|
|||
virtual Target*
|
||||
do_instantiate_target() = 0;
|
||||
|
||||
// Recognize an object file given a machine code, size, and
|
||||
// endianness. When this is called we already know that they match
|
||||
// the machine_, size_, and is_big_endian_ fields. The child class
|
||||
// may implement a different version of this to do additional
|
||||
// Recognize an object file given a machine code, OSABI code, and
|
||||
// ELF version value. When this is called we already know that they
|
||||
// match the machine_, size_, and is_big_endian_ fields. The child
|
||||
// class may implement a different version of this to do additional
|
||||
// checks, or to check for multiple machine codes if the machine_
|
||||
// field is EM_NONE.
|
||||
virtual Target*
|
||||
|
@ -134,7 +134,6 @@ class Target_selector
|
|||
names->push_back(this->bfd_name_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Instantiate the target and return it.
|
||||
Target*
|
||||
instantiate_target()
|
||||
|
@ -144,6 +143,7 @@ class Target_selector
|
|||
return this->instantiated_target_;
|
||||
}
|
||||
|
||||
private:
|
||||
// ELF machine code.
|
||||
const int machine_;
|
||||
// Target size--32 or 64.
|
||||
|
|
|
@ -167,6 +167,12 @@ class Target
|
|||
is_defined_by_abi(const Symbol* sym) const
|
||||
{ return this->do_is_defined_by_abi(sym); }
|
||||
|
||||
// Adjust the output file header before it is written out. VIEW
|
||||
// points to the header in external form. LEN is the length.
|
||||
void
|
||||
adjust_elf_header(unsigned char* view, int len) const
|
||||
{ return this->do_adjust_elf_header(view, len); }
|
||||
|
||||
protected:
|
||||
// This struct holds the constant information for a child class. We
|
||||
// use a struct to avoid the overhead of virtual function calls for
|
||||
|
@ -225,6 +231,14 @@ class Target
|
|||
do_is_defined_by_abi(const Symbol*) const
|
||||
{ return false; }
|
||||
|
||||
// Adjust the output file header before it is written out. VIEW
|
||||
// points to the header in external form. LEN is the length, and
|
||||
// will be one of the values of elfcpp::Elf_sizes<size>::ehdr_size.
|
||||
// By default, we do nothing.
|
||||
virtual void
|
||||
do_adjust_elf_header(unsigned char*, int) const
|
||||
{ }
|
||||
|
||||
private:
|
||||
Target(const Target&);
|
||||
Target& operator=(const Target&);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "target-reloc.h"
|
||||
#include "target-select.h"
|
||||
#include "tls.h"
|
||||
#include "freebsd.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -52,7 +53,7 @@ class Output_data_plt_x86_64;
|
|||
// http://people.redhat.com/drepper/tls.pdf
|
||||
// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt
|
||||
|
||||
class Target_x86_64 : public Sized_target<64, false>
|
||||
class Target_x86_64 : public Target_freebsd<64, false>
|
||||
{
|
||||
public:
|
||||
// In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures
|
||||
|
@ -60,7 +61,7 @@ class Target_x86_64 : public Sized_target<64, false>
|
|||
typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
|
||||
|
||||
Target_x86_64()
|
||||
: Sized_target<64, false>(&x86_64_info),
|
||||
: Target_freebsd<64, false>(&x86_64_info),
|
||||
got_(NULL), plt_(NULL), got_plt_(NULL), rela_dyn_(NULL),
|
||||
copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
|
||||
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
|
||||
|
@ -2648,16 +2649,18 @@ Target_x86_64::do_code_fill(section_size_type length) const
|
|||
|
||||
// The selector for x86_64 object files.
|
||||
|
||||
class Target_selector_x86_64 : public Target_selector
|
||||
class Target_selector_x86_64 : public Target_selector_freebsd
|
||||
{
|
||||
public:
|
||||
Target_selector_x86_64()
|
||||
: Target_selector(elfcpp::EM_X86_64, 64, false, "elf64-x86-64")
|
||||
: Target_selector_freebsd(elfcpp::EM_X86_64, 64, false, "elf64-x86-64",
|
||||
"elf64-x86-64-freebsd")
|
||||
{ }
|
||||
|
||||
Target*
|
||||
do_instantiate_target()
|
||||
{ return new Target_x86_64(); }
|
||||
|
||||
};
|
||||
|
||||
Target_selector_x86_64 target_selector_x86_64;
|
||||
|
|
Loading…
Reference in a new issue