1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
// copy-relocs.h -- handle COPY relocations for gold -*- C++ -*-
// Copyright (C) 2006-2020 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)
|