// freebsd.h -- FreeBSD support for gold -*- C++ -*- // Copyright 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // 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 class Target_freebsd : public Sized_target { 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(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 inline void Target_freebsd::do_adjust_elf_header(unsigned char* view, int len) const { if (this->osabi_ != elfcpp::ELFOSABI_NONE) { gold_assert(len == elfcpp::Elf_sizes::ehdr_size); elfcpp::Ehdr 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 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* 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)-> set_osabi(elfcpp::ELFOSABI_FREEBSD); else static_cast*>(target)-> set_osabi(elfcpp::ELFOSABI_FREEBSD); } else if (this->get_size() == 64) { if (this->is_big_endian()) static_cast*>(target)-> set_osabi(elfcpp::ELFOSABI_FREEBSD); else static_cast*>(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)