diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-03-24 00:31:29 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-03-24 00:31:29 +0000 |
commit | 36959681867a70c8f48055ffb22b6f037596b762 (patch) | |
tree | 46b20dfcf1d79a1ac3f5e12d2e03a0cde21e912e /gold/freebsd.h | |
parent | d739bf00691a4e5a8c002dc7eb5d49bb4ad95d24 (diff) | |
download | gdb-36959681867a70c8f48055ffb22b6f037596b762.zip gdb-36959681867a70c8f48055ffb22b6f037596b762.tar.gz gdb-36959681867a70c8f48055ffb22b6f037596b762.tar.bz2 |
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.
Diffstat (limited to 'gold/freebsd.h')
-rw-r--r-- | gold/freebsd.h | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/gold/freebsd.h b/gold/freebsd.h new file mode 100644 index 0000000..f98efaf --- /dev/null +++ b/gold/freebsd.h @@ -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) |