| // copy-relocs.h -- handle COPY relocations for gold   -*- C++ -*- | 
 |  | 
 | // Copyright (C) 2006-2024 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. | 
 |  | 
 | #ifndef GOLD_COPY_RELOCS_H | 
 | #define GOLD_COPY_RELOCS_H | 
 |  | 
 | #include "elfcpp.h" | 
 | #include "reloc-types.h" | 
 | #include "output.h" | 
 |  | 
 | namespace gold | 
 | { | 
 |  | 
 | // This class is used to manage COPY relocations.  We try to avoid | 
 | // them when possible.  A COPY relocation may be required when an | 
 | // executable refers to a variable defined in a shared library.  COPY | 
 | // relocations are problematic because they tie the executable to the | 
 | // exact size of the variable in the shared library.  We can avoid | 
 | // them if all the references to the variable are in a writeable | 
 | // section.  In that case we can simply use dynamic relocations. | 
 | // However, when scanning relocs, we don't know when we see the | 
 | // relocation whether we will be forced to use a COPY relocation or | 
 | // not.  So we have to save the relocation during the reloc scanning, | 
 | // and then emit it as a dynamic relocation if necessary.  This class | 
 | // implements that.  It is used by the target specific code. | 
 |  | 
 | // The template parameter SH_TYPE is the type of the reloc section to | 
 | // be used for COPY relocs: elfcpp::SHT_REL or elfcpp::SHT_RELA. | 
 |  | 
 | template<int sh_type, int size, bool big_endian> | 
 | class Copy_relocs | 
 | { | 
 |  private: | 
 |   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reloc; | 
 |  | 
 |  public: | 
 |   Copy_relocs(unsigned int copy_reloc_type) | 
 |     : entries_(), copy_reloc_type_(copy_reloc_type), dynbss_(NULL), | 
 |       dynrelro_(NULL) | 
 |   { } | 
 |  | 
 |   // This is called while scanning relocs if we see a relocation | 
 |   // against a symbol which may force us to generate a COPY reloc. | 
 |   // SYM is the symbol.  OBJECT is the object whose relocs we are | 
 |   // scanning.  The relocation is being applied to section SHNDX in | 
 |   // OBJECT.  OUTPUT_SECTION is the output section where section SHNDX | 
 |   // will wind up.  REL is the reloc itself.  The Output_data_reloc | 
 |   // section is where the dynamic relocs are put. | 
 |   void | 
 |   copy_reloc(Symbol_table*, | 
 | 	     Layout*, | 
 | 	     Sized_symbol<size>* sym, | 
 |              Sized_relobj_file<size, big_endian>* object, | 
 | 	     unsigned int shndx, | 
 | 	     Output_section* output_section, | 
 | 	     unsigned int r_type, | 
 | 	     typename elfcpp::Elf_types<size>::Elf_Addr r_offset, | 
 | 	     typename elfcpp::Elf_types<size>::Elf_Swxword r_addend, | 
 | 	     Output_data_reloc<sh_type, true, size, big_endian>*); | 
 |  | 
 |   // Return whether there are any saved relocations. | 
 |   bool | 
 |   any_saved_relocs() const | 
 |   { return !this->entries_.empty(); } | 
 |  | 
 |   // Emit any saved relocations which turn out to be needed.  This is | 
 |   // called after all the relocs have been scanned. | 
 |   void | 
 |   emit(Output_data_reloc<sh_type, true, size, big_endian>*); | 
 |  | 
 |   // Emit a COPY reloc. | 
 |   void | 
 |   emit_copy_reloc(Symbol_table*, Sized_symbol<size>*, | 
 | 		  Output_data*, off_t, | 
 | 		  Output_data_reloc<sh_type, true, size, big_endian>*); | 
 |  | 
 |  protected: | 
 |   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; | 
 |   typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend; | 
 |  | 
 |   // This POD class holds the relocations we are saving.  We will emit | 
 |   // these relocations if it turns out that the symbol does not | 
 |   // require a COPY relocation. | 
 |   struct Copy_reloc_entry | 
 |   { | 
 |     Copy_reloc_entry(Symbol* sym, unsigned int reloc_type, | 
 | 		     Sized_relobj_file<size, big_endian>* relobj, | 
 |                      unsigned int shndx, | 
 | 		     Output_section* output_section, | 
 | 		     Address address, Addend addend) | 
 |       : sym_(sym), reloc_type_(reloc_type), relobj_(relobj), | 
 | 	shndx_(shndx), output_section_(output_section), | 
 | 	address_(address), addend_(addend) | 
 |     { } | 
 |  | 
 |     Symbol* sym_; | 
 |     unsigned int reloc_type_; | 
 |     Sized_relobj_file<size, big_endian>* relobj_; | 
 |     unsigned int shndx_; | 
 |     Output_section* output_section_; | 
 |     Address address_; | 
 |     Addend addend_; | 
 |   }; | 
 |  | 
 |   // Make a new COPY reloc and emit it. | 
 |   void | 
 |   make_copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>*, | 
 | 		  Sized_relobj_file<size, big_endian>* object, | 
 | 		  Output_data_reloc<sh_type, true, size, big_endian>*); | 
 |  | 
 |   // A list of relocs to be saved. | 
 |   typedef std::vector<Copy_reloc_entry> Copy_reloc_entries; | 
 |  | 
 |   // The list of relocs we are saving. | 
 |   Copy_reloc_entries entries_; | 
 |  | 
 |  private: | 
 |   // Return whether we need a COPY reloc. | 
 |   bool | 
 |   need_copy_reloc(Sized_symbol<size>* gsym, | 
 |                   Sized_relobj_file<size, big_endian>* object, | 
 | 		  unsigned int shndx) const; | 
 |  | 
 |   // Save a reloc against SYM for possible emission later. | 
 |   void | 
 |   save(Symbol*, | 
 |        Sized_relobj_file<size, big_endian>*, | 
 |        unsigned int shndx, | 
 |        Output_section*, | 
 |        unsigned int r_type, | 
 |        typename elfcpp::Elf_types<size>::Elf_Addr r_offset, | 
 |        typename elfcpp::Elf_types<size>::Elf_Swxword r_addend); | 
 |  | 
 |   // The target specific relocation type of the COPY relocation. | 
 |   const unsigned int copy_reloc_type_; | 
 |   // The dynamic BSS data which goes into the .bss section.  This is | 
 |   // where writable variables which require COPY relocations are placed. | 
 |   Output_data_space* dynbss_; | 
 |   // The dynamic read-only data, which goes into the .data.rel.ro section. | 
 |   // This is where read-only variables which require COPY relocations are | 
 |   // placed. | 
 |   Output_data_space* dynrelro_; | 
 | }; | 
 |  | 
 | } // End namespace gold. | 
 |  | 
 | #endif // !defined(GOLD_COPY_RELOCS_H) |