1  // copy-relocs.h -- handle COPY relocations for gold   -*- C++ -*-
       2  
       3  // Copyright (C) 2006-2023 Free Software Foundation, Inc.
       4  // Written by Ian Lance Taylor <iant@google.com>.
       5  
       6  // This file is part of gold.
       7  
       8  // This program is free software; you can redistribute it and/or modify
       9  // it under the terms of the GNU General Public License as published by
      10  // the Free Software Foundation; either version 3 of the License, or
      11  // (at your option) any later version.
      12  
      13  // This program is distributed in the hope that it will be useful,
      14  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      15  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16  // GNU General Public License for more details.
      17  
      18  // You should have received a copy of the GNU General Public License
      19  // along with this program; if not, write to the Free Software
      20  // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21  // MA 02110-1301, USA.
      22  
      23  #ifndef GOLD_COPY_RELOCS_H
      24  #define GOLD_COPY_RELOCS_H
      25  
      26  #include "elfcpp.h"
      27  #include "reloc-types.h"
      28  #include "output.h"
      29  
      30  namespace gold
      31  {
      32  
      33  // This class is used to manage COPY relocations.  We try to avoid
      34  // them when possible.  A COPY relocation may be required when an
      35  // executable refers to a variable defined in a shared library.  COPY
      36  // relocations are problematic because they tie the executable to the
      37  // exact size of the variable in the shared library.  We can avoid
      38  // them if all the references to the variable are in a writeable
      39  // section.  In that case we can simply use dynamic relocations.
      40  // However, when scanning relocs, we don't know when we see the
      41  // relocation whether we will be forced to use a COPY relocation or
      42  // not.  So we have to save the relocation during the reloc scanning,
      43  // and then emit it as a dynamic relocation if necessary.  This class
      44  // implements that.  It is used by the target specific code.
      45  
      46  // The template parameter SH_TYPE is the type of the reloc section to
      47  // be used for COPY relocs: elfcpp::SHT_REL or elfcpp::SHT_RELA.
      48  
      49  template<int sh_type, int size, bool big_endian>
      50  class Copy_relocs
      51  {
      52   private:
      53    typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reloc;
      54  
      55   public:
      56    Copy_relocs(unsigned int copy_reloc_type)
      57      : entries_(), copy_reloc_type_(copy_reloc_type), dynbss_(NULL),
      58        dynrelro_(NULL)
      59    { }
      60  
      61    // This is called while scanning relocs if we see a relocation
      62    // against a symbol which may force us to generate a COPY reloc.
      63    // SYM is the symbol.  OBJECT is the object whose relocs we are
      64    // scanning.  The relocation is being applied to section SHNDX in
      65    // OBJECT.  OUTPUT_SECTION is the output section where section SHNDX
      66    // will wind up.  REL is the reloc itself.  The Output_data_reloc
      67    // section is where the dynamic relocs are put.
      68    void
      69    copy_reloc(Symbol_table*,
      70  	     Layout*,
      71  	     Sized_symbol<size>* sym,
      72               Sized_relobj_file<size, big_endian>* object,
      73  	     unsigned int shndx,
      74  	     Output_section* output_section,
      75  	     unsigned int r_type,
      76  	     typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
      77  	     typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
      78  	     Output_data_reloc<sh_type, true, size, big_endian>*);
      79  
      80    // Return whether there are any saved relocations.
      81    bool
      82    any_saved_relocs() const
      83    { return !this->entries_.empty(); }
      84  
      85    // Emit any saved relocations which turn out to be needed.  This is
      86    // called after all the relocs have been scanned.
      87    void
      88    emit(Output_data_reloc<sh_type, true, size, big_endian>*);
      89  
      90    // Emit a COPY reloc.
      91    void
      92    emit_copy_reloc(Symbol_table*, Sized_symbol<size>*,
      93  		  Output_data*, off_t,
      94  		  Output_data_reloc<sh_type, true, size, big_endian>*);
      95  
      96   protected:
      97    typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
      98    typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
      99  
     100    // This POD class holds the relocations we are saving.  We will emit
     101    // these relocations if it turns out that the symbol does not
     102    // require a COPY relocation.
     103    struct Copy_reloc_entry
     104    {
     105      Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
     106  		     Sized_relobj_file<size, big_endian>* relobj,
     107                       unsigned int shndx,
     108  		     Output_section* output_section,
     109  		     Address address, Addend addend)
     110        : sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
     111  	shndx_(shndx), output_section_(output_section),
     112  	address_(address), addend_(addend)
     113      { }
     114  
     115      Symbol* sym_;
     116      unsigned int reloc_type_;
     117      Sized_relobj_file<size, big_endian>* relobj_;
     118      unsigned int shndx_;
     119      Output_section* output_section_;
     120      Address address_;
     121      Addend addend_;
     122    };
     123  
     124    // Make a new COPY reloc and emit it.
     125    void
     126    make_copy_reloc(Symbol_table*, Layout*, Sized_symbol<size>*,
     127  		  Sized_relobj_file<size, big_endian>* object,
     128  		  Output_data_reloc<sh_type, true, size, big_endian>*);
     129  
     130    // A list of relocs to be saved.
     131    typedef std::vector<Copy_reloc_entry> Copy_reloc_entries;
     132  
     133    // The list of relocs we are saving.
     134    Copy_reloc_entries entries_;
     135  
     136   private:
     137    // Return whether we need a COPY reloc.
     138    bool
     139    need_copy_reloc(Sized_symbol<size>* gsym,
     140                    Sized_relobj_file<size, big_endian>* object,
     141  		  unsigned int shndx) const;
     142  
     143    // Save a reloc against SYM for possible emission later.
     144    void
     145    save(Symbol*,
     146         Sized_relobj_file<size, big_endian>*,
     147         unsigned int shndx,
     148         Output_section*,
     149         unsigned int r_type,
     150         typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
     151         typename elfcpp::Elf_types<size>::Elf_Swxword r_addend);
     152  
     153    // The target specific relocation type of the COPY relocation.
     154    const unsigned int copy_reloc_type_;
     155    // The dynamic BSS data which goes into the .bss section.  This is
     156    // where writable variables which require COPY relocations are placed.
     157    Output_data_space* dynbss_;
     158    // The dynamic read-only data, which goes into the .data.rel.ro section.
     159    // This is where read-only variables which require COPY relocations are
     160    // placed.
     161    Output_data_space* dynrelro_;
     162  };
     163  
     164  } // End namespace gold.
     165  
     166  #endif // !defined(GOLD_COPY_RELOCS_H)