mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 07:08:01 +08:00
Implement -q/--emit-relocs.
This commit is contained in:
@ -2297,7 +2297,7 @@ Target_i386::scan_relocatable_relocs(const General_options& options,
|
|||||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
|
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
|
||||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||||
|
|
||||||
gold::scan_relocatable_relocs<32, false, Target_i386, elfcpp::SHT_REL,
|
gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL,
|
||||||
Scan_relocatable_relocs>(
|
Scan_relocatable_relocs>(
|
||||||
options,
|
options,
|
||||||
symtab,
|
symtab,
|
||||||
@ -2332,7 +2332,7 @@ Target_i386::relocate_for_relocatable(
|
|||||||
{
|
{
|
||||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||||
|
|
||||||
gold::relocate_for_relocatable<32, false, Target_i386, elfcpp::SHT_REL>(
|
gold::relocate_for_relocatable<32, false, elfcpp::SHT_REL>(
|
||||||
relinfo,
|
relinfo,
|
||||||
prelocs,
|
prelocs,
|
||||||
reloc_count,
|
reloc_count,
|
||||||
|
@ -155,8 +155,10 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
|
|||||||
case elfcpp::SHT_RELA:
|
case elfcpp::SHT_RELA:
|
||||||
case elfcpp::SHT_REL:
|
case elfcpp::SHT_REL:
|
||||||
case elfcpp::SHT_GROUP:
|
case elfcpp::SHT_GROUP:
|
||||||
// For a relocatable link these should be handled elsewhere.
|
// If we are emitting relocations these should be handled
|
||||||
gold_assert(!parameters->output_is_object());
|
// elsewhere.
|
||||||
|
gold_assert(!parameters->output_is_object()
|
||||||
|
&& !parameters->emit_relocs());
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case elfcpp::SHT_PROGBITS:
|
case elfcpp::SHT_PROGBITS:
|
||||||
@ -370,7 +372,7 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
|
|||||||
Output_section* data_section,
|
Output_section* data_section,
|
||||||
Relocatable_relocs* rr)
|
Relocatable_relocs* rr)
|
||||||
{
|
{
|
||||||
gold_assert(parameters->output_is_object());
|
gold_assert(parameters->output_is_object() || parameters->emit_relocs());
|
||||||
|
|
||||||
int sh_type = shdr.get_sh_type();
|
int sh_type = shdr.get_sh_type();
|
||||||
|
|
||||||
|
@ -593,8 +593,9 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
|
|||||||
// Keep track of which sections to omit.
|
// Keep track of which sections to omit.
|
||||||
std::vector<bool> omit(shnum, false);
|
std::vector<bool> omit(shnum, false);
|
||||||
|
|
||||||
// Keep track of reloc sections when doing a relocatable link.
|
// Keep track of reloc sections when emitting relocations.
|
||||||
const bool output_is_object = parameters->output_is_object();
|
const bool output_is_object = parameters->output_is_object();
|
||||||
|
const bool emit_relocs = output_is_object || parameters->emit_relocs();
|
||||||
std::vector<unsigned int> reloc_sections;
|
std::vector<unsigned int> reloc_sections;
|
||||||
|
|
||||||
// Keep track of .eh_frame sections.
|
// Keep track of .eh_frame sections.
|
||||||
@ -660,7 +661,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
|
|||||||
// ones associated with sections which are not being discarded.
|
// ones associated with sections which are not being discarded.
|
||||||
// However, we don't know that yet for all sections. So save
|
// However, we don't know that yet for all sections. So save
|
||||||
// reloc sections and process them later.
|
// reloc sections and process them later.
|
||||||
if (output_is_object
|
if (emit_relocs
|
||||||
&& (shdr.get_sh_type() == elfcpp::SHT_REL
|
&& (shdr.get_sh_type() == elfcpp::SHT_REL
|
||||||
|| shdr.get_sh_type() == elfcpp::SHT_RELA))
|
|| shdr.get_sh_type() == elfcpp::SHT_RELA))
|
||||||
{
|
{
|
||||||
@ -704,7 +705,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
|
|||||||
|
|
||||||
// When doing a relocatable link handle the reloc sections at the
|
// When doing a relocatable link handle the reloc sections at the
|
||||||
// end.
|
// end.
|
||||||
if (output_is_object)
|
if (emit_relocs)
|
||||||
this->size_relocatable_relocs();
|
this->size_relocatable_relocs();
|
||||||
for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
|
for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
|
||||||
p != reloc_sections.end();
|
p != reloc_sections.end();
|
||||||
|
@ -111,6 +111,8 @@ struct Section_relocs
|
|||||||
Output_section* output_section;
|
Output_section* output_section;
|
||||||
// Whether this section has special handling for offsets.
|
// Whether this section has special handling for offsets.
|
||||||
bool needs_special_offset_handling;
|
bool needs_special_offset_handling;
|
||||||
|
// Whether the data section is allocated (has the SHF_ALLOC flag set).
|
||||||
|
bool is_data_section_allocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Relocations in an object file. This is read in read_relocs and
|
// Relocations in an object file. This is read in read_relocs and
|
||||||
@ -1312,6 +1314,42 @@ class Sized_relobj : public Relobj
|
|||||||
relocate_sections(const General_options& options, const Symbol_table*,
|
relocate_sections(const General_options& options, const Symbol_table*,
|
||||||
const Layout*, const unsigned char* pshdrs, Views*);
|
const Layout*, const unsigned char* pshdrs, Views*);
|
||||||
|
|
||||||
|
// Scan the input relocations for --emit-relocs.
|
||||||
|
void
|
||||||
|
emit_relocs_scan(const General_options&, Symbol_table*, Layout*,
|
||||||
|
const unsigned char* plocal_syms,
|
||||||
|
const Read_relocs_data::Relocs_list::iterator&);
|
||||||
|
|
||||||
|
// Scan the input relocations for --emit-relocs, templatized on the
|
||||||
|
// type of the relocation section.
|
||||||
|
template<int sh_type>
|
||||||
|
void
|
||||||
|
emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*,
|
||||||
|
const unsigned char* plocal_syms,
|
||||||
|
const Read_relocs_data::Relocs_list::iterator&,
|
||||||
|
Relocatable_relocs*);
|
||||||
|
|
||||||
|
// Emit the relocs for --emit-relocs.
|
||||||
|
void
|
||||||
|
emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
|
||||||
|
unsigned int sh_type, const unsigned char* prelocs,
|
||||||
|
size_t reloc_count, Output_section*, off_t output_offset,
|
||||||
|
unsigned char* view, Address address,
|
||||||
|
section_size_type view_size,
|
||||||
|
unsigned char* reloc_view, section_size_type reloc_view_size);
|
||||||
|
|
||||||
|
// Emit the relocs for --emit-relocs, templatized on the type of the
|
||||||
|
// relocation section.
|
||||||
|
template<int sh_type>
|
||||||
|
void
|
||||||
|
emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
|
||||||
|
const unsigned char* prelocs, size_t reloc_count,
|
||||||
|
Output_section*, off_t output_offset,
|
||||||
|
unsigned char* view, Address address,
|
||||||
|
section_size_type view_size,
|
||||||
|
unsigned char* reloc_view,
|
||||||
|
section_size_type reloc_view_size);
|
||||||
|
|
||||||
// Initialize input to output maps for section symbols in merged
|
// Initialize input to output maps for section symbols in merged
|
||||||
// sections.
|
// sections.
|
||||||
void
|
void
|
||||||
|
@ -530,8 +530,10 @@ options::Command_line_options::options[] =
|
|||||||
GENERAL_ARG('\0', "oformat", N_("Set output format (only binary supported)"),
|
GENERAL_ARG('\0', "oformat", N_("Set output format (only binary supported)"),
|
||||||
N_("--oformat FORMAT"), EXACTLY_TWO_DASHES,
|
N_("--oformat FORMAT"), EXACTLY_TWO_DASHES,
|
||||||
&General_options::set_oformat),
|
&General_options::set_oformat),
|
||||||
|
GENERAL_NOARG('q', "emit-relocs", N_("Generate relocations in output"),
|
||||||
|
NULL, TWO_DASHES, &General_options::set_emit_relocs),
|
||||||
GENERAL_NOARG('r', "relocatable", N_("Generate relocatable output"), NULL,
|
GENERAL_NOARG('r', "relocatable", N_("Generate relocatable output"), NULL,
|
||||||
ONE_DASH, &General_options::set_relocatable),
|
TWO_DASHES, &General_options::set_relocatable),
|
||||||
// -R really means -rpath, but can mean --just-symbols for
|
// -R really means -rpath, but can mean --just-symbols for
|
||||||
// compatibility with GNU ld. -rpath is always -rpath, so we list
|
// compatibility with GNU ld. -rpath is always -rpath, so we list
|
||||||
// it separately.
|
// it separately.
|
||||||
@ -672,6 +674,7 @@ General_options::General_options()
|
|||||||
output_file_name_("a.out"),
|
output_file_name_("a.out"),
|
||||||
oformat_(OBJECT_FORMAT_ELF),
|
oformat_(OBJECT_FORMAT_ELF),
|
||||||
oformat_string_(NULL),
|
oformat_string_(NULL),
|
||||||
|
emit_relocs_(false),
|
||||||
is_relocatable_(false),
|
is_relocatable_(false),
|
||||||
strip_(STRIP_NONE),
|
strip_(STRIP_NONE),
|
||||||
allow_shlib_undefined_(false),
|
allow_shlib_undefined_(false),
|
||||||
|
@ -167,6 +167,11 @@ class General_options
|
|||||||
Target*
|
Target*
|
||||||
default_target() const;
|
default_target() const;
|
||||||
|
|
||||||
|
// -q: Whether to emit relocations.
|
||||||
|
bool
|
||||||
|
emit_relocs() const
|
||||||
|
{ return this->emit_relocs_; }
|
||||||
|
|
||||||
// -r: Whether we are doing a relocatable link.
|
// -r: Whether we are doing a relocatable link.
|
||||||
bool
|
bool
|
||||||
relocatable() const
|
relocatable() const
|
||||||
@ -408,6 +413,10 @@ class General_options
|
|||||||
void
|
void
|
||||||
set_oformat(const char*);
|
set_oformat(const char*);
|
||||||
|
|
||||||
|
void
|
||||||
|
set_emit_relocs(bool value)
|
||||||
|
{ this->emit_relocs_ = value; }
|
||||||
|
|
||||||
void
|
void
|
||||||
set_relocatable(bool value)
|
set_relocatable(bool value)
|
||||||
{ this->is_relocatable_ = value; }
|
{ this->is_relocatable_ = value; }
|
||||||
@ -615,6 +624,7 @@ class General_options
|
|||||||
const char* output_file_name_;
|
const char* output_file_name_;
|
||||||
Object_format oformat_;
|
Object_format oformat_;
|
||||||
const char* oformat_string_;
|
const char* oformat_string_;
|
||||||
|
bool emit_relocs_;
|
||||||
bool is_relocatable_;
|
bool is_relocatable_;
|
||||||
Strip strip_;
|
Strip strip_;
|
||||||
bool allow_shlib_undefined_;
|
bool allow_shlib_undefined_;
|
||||||
|
@ -33,7 +33,7 @@ namespace gold
|
|||||||
|
|
||||||
Parameters::Parameters(Errors* errors)
|
Parameters::Parameters(Errors* errors)
|
||||||
: errors_(errors), threads_(false), output_file_name_(NULL),
|
: errors_(errors), threads_(false), output_file_name_(NULL),
|
||||||
output_file_type_(OUTPUT_INVALID), sysroot_(),
|
output_file_type_(OUTPUT_INVALID), emit_relocs_(false), sysroot_(),
|
||||||
strip_(STRIP_INVALID), allow_shlib_undefined_(false),
|
strip_(STRIP_INVALID), allow_shlib_undefined_(false),
|
||||||
symbolic_(false), demangle_(false), detect_odr_violations_(false),
|
symbolic_(false), demangle_(false), detect_odr_violations_(false),
|
||||||
optimization_level_(0), export_dynamic_(false), debug_(0),
|
optimization_level_(0), export_dynamic_(false), debug_(0),
|
||||||
@ -50,6 +50,7 @@ Parameters::set_from_options(const General_options* options)
|
|||||||
{
|
{
|
||||||
this->threads_ = options->threads();
|
this->threads_ = options->threads();
|
||||||
this->output_file_name_ = options->output_file_name();
|
this->output_file_name_ = options->output_file_name();
|
||||||
|
this->emit_relocs_ = options->emit_relocs();
|
||||||
this->sysroot_ = options->sysroot();
|
this->sysroot_ = options->sysroot();
|
||||||
this->allow_shlib_undefined_ = options->allow_shlib_undefined();
|
this->allow_shlib_undefined_ = options->allow_shlib_undefined();
|
||||||
this->symbolic_ = options->Bsymbolic();
|
this->symbolic_ = options->Bsymbolic();
|
||||||
|
@ -102,6 +102,11 @@ class Parameters
|
|||||||
output_is_position_independent() const
|
output_is_position_independent() const
|
||||||
{ return output_is_shared(); }
|
{ return output_is_shared(); }
|
||||||
|
|
||||||
|
// Whether to emit relocations in the output.
|
||||||
|
bool
|
||||||
|
emit_relocs() const
|
||||||
|
{ return this->emit_relocs_; }
|
||||||
|
|
||||||
// The target system root directory. This is NULL if there isn't
|
// The target system root directory. This is NULL if there isn't
|
||||||
// one.
|
// one.
|
||||||
const std::string&
|
const std::string&
|
||||||
@ -298,6 +303,8 @@ class Parameters
|
|||||||
const char* output_file_name_;
|
const char* output_file_name_;
|
||||||
// The type of the output file.
|
// The type of the output file.
|
||||||
Output_file_type output_file_type_;
|
Output_file_type output_file_type_;
|
||||||
|
// Whether to emit relocations (-q/--emit-relocs).
|
||||||
|
bool emit_relocs_;
|
||||||
// The target system root directory.
|
// The target system root directory.
|
||||||
std::string sysroot_;
|
std::string sysroot_;
|
||||||
// Which symbols to strip.
|
// Which symbols to strip.
|
||||||
|
235
gold/reloc.cc
235
gold/reloc.cc
@ -29,6 +29,7 @@
|
|||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "merge.h"
|
#include "merge.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "target-reloc.h"
|
||||||
#include "reloc.h"
|
#include "reloc.h"
|
||||||
|
|
||||||
namespace gold
|
namespace gold
|
||||||
@ -223,13 +224,14 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
|||||||
// PLT sections. Relocations for sections which are not
|
// PLT sections. Relocations for sections which are not
|
||||||
// allocated (typically debugging sections) should not add new
|
// allocated (typically debugging sections) should not add new
|
||||||
// GOT and PLT entries. So we skip them unless this is a
|
// GOT and PLT entries. So we skip them unless this is a
|
||||||
// relocatable link.
|
// relocatable link or we need to emit relocations.
|
||||||
if (!parameters->output_is_object())
|
typename This::Shdr secshdr(pshdrs + shndx * This::shdr_size);
|
||||||
{
|
bool is_section_allocated = ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC)
|
||||||
typename This::Shdr secshdr(pshdrs + shndx * This::shdr_size);
|
!= 0);
|
||||||
if ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
|
if (!is_section_allocated
|
||||||
continue;
|
&& !parameters->output_is_object()
|
||||||
}
|
&& !parameters->emit_relocs())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (shdr.get_sh_link() != this->symtab_shndx_)
|
if (shdr.get_sh_link() != this->symtab_shndx_)
|
||||||
{
|
{
|
||||||
@ -272,6 +274,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
|||||||
sr.reloc_count = reloc_count;
|
sr.reloc_count = reloc_count;
|
||||||
sr.output_section = os;
|
sr.output_section = os;
|
||||||
sr.needs_special_offset_handling = map_sections[shndx].offset == -1;
|
sr.needs_special_offset_handling = map_sections[shndx].offset == -1;
|
||||||
|
sr.is_data_section_allocated = is_section_allocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the local symbols.
|
// Read the local symbols.
|
||||||
@ -315,12 +318,20 @@ Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options,
|
|||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
if (!parameters->output_is_object())
|
if (!parameters->output_is_object())
|
||||||
target->scan_relocs(options, symtab, layout, this, p->data_shndx,
|
{
|
||||||
p->sh_type, p->contents->data(), p->reloc_count,
|
// As noted above, when not generating an object file, we
|
||||||
p->output_section,
|
// only scan allocated sections. We may see a non-allocated
|
||||||
p->needs_special_offset_handling,
|
// section here if we are emitting relocs.
|
||||||
this->local_symbol_count_,
|
if (p->is_data_section_allocated)
|
||||||
local_symbols);
|
target->scan_relocs(options, symtab, layout, this, p->data_shndx,
|
||||||
|
p->sh_type, p->contents->data(),
|
||||||
|
p->reloc_count, p->output_section,
|
||||||
|
p->needs_special_offset_handling,
|
||||||
|
this->local_symbol_count_,
|
||||||
|
local_symbols);
|
||||||
|
if (parameters->emit_relocs())
|
||||||
|
this->emit_relocs_scan(options, symtab, layout, local_symbols, p);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
|
Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
|
||||||
@ -348,6 +359,98 @@ Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a strategy class we use when scanning for --emit-relocs.
|
||||||
|
|
||||||
|
template<int sh_type>
|
||||||
|
class Emit_relocs_strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// A local non-section symbol.
|
||||||
|
inline Relocatable_relocs::Reloc_strategy
|
||||||
|
local_non_section_strategy(unsigned int, Relobj*)
|
||||||
|
{ return Relocatable_relocs::RELOC_COPY; }
|
||||||
|
|
||||||
|
// A local section symbol.
|
||||||
|
inline Relocatable_relocs::Reloc_strategy
|
||||||
|
local_section_strategy(unsigned int, Relobj*)
|
||||||
|
{
|
||||||
|
if (sh_type == elfcpp::SHT_RELA)
|
||||||
|
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The addend is stored in the section contents. Since this
|
||||||
|
// is not a relocatable link, we are going to apply the
|
||||||
|
// relocation contents to the section as usual. This means
|
||||||
|
// that we have no way to record the original addend. If the
|
||||||
|
// original addend is not zero, there is basically no way for
|
||||||
|
// the user to handle this correctly. Caveat emptor.
|
||||||
|
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A global symbol.
|
||||||
|
inline Relocatable_relocs::Reloc_strategy
|
||||||
|
global_strategy(unsigned int, Relobj*, unsigned int)
|
||||||
|
{ return Relocatable_relocs::RELOC_COPY; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scan the input relocations for --emit-relocs.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Sized_relobj<size, big_endian>::emit_relocs_scan(
|
||||||
|
const General_options& options,
|
||||||
|
Symbol_table* symtab,
|
||||||
|
Layout* layout,
|
||||||
|
const unsigned char* plocal_syms,
|
||||||
|
const Read_relocs_data::Relocs_list::iterator& p)
|
||||||
|
{
|
||||||
|
Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
|
||||||
|
gold_assert(rr != NULL);
|
||||||
|
rr->set_reloc_count(p->reloc_count);
|
||||||
|
|
||||||
|
if (p->sh_type == elfcpp::SHT_REL)
|
||||||
|
this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(options, symtab, layout,
|
||||||
|
plocal_syms, p, rr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gold_assert(p->sh_type == elfcpp::SHT_RELA);
|
||||||
|
this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(options, symtab,
|
||||||
|
layout, plocal_syms, p,
|
||||||
|
rr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the input relocation for --emit-relocs, templatized on the
|
||||||
|
// type of the relocation section.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
template<int sh_type>
|
||||||
|
void
|
||||||
|
Sized_relobj<size, big_endian>::emit_relocs_scan_reltype(
|
||||||
|
const General_options& options,
|
||||||
|
Symbol_table* symtab,
|
||||||
|
Layout* layout,
|
||||||
|
const unsigned char* plocal_syms,
|
||||||
|
const Read_relocs_data::Relocs_list::iterator& p,
|
||||||
|
Relocatable_relocs* rr)
|
||||||
|
{
|
||||||
|
scan_relocatable_relocs<size, big_endian, sh_type,
|
||||||
|
Emit_relocs_strategy<sh_type> >(
|
||||||
|
options,
|
||||||
|
symtab,
|
||||||
|
layout,
|
||||||
|
this,
|
||||||
|
p->data_shndx,
|
||||||
|
p->contents->data(),
|
||||||
|
p->reloc_count,
|
||||||
|
p->output_section,
|
||||||
|
p->needs_special_offset_handling,
|
||||||
|
this->local_symbol_count_,
|
||||||
|
plocal_syms,
|
||||||
|
rr);
|
||||||
|
}
|
||||||
|
|
||||||
// Relocate the input sections and write out the local symbols.
|
// Relocate the input sections and write out the local symbols.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -452,14 +555,15 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
|
|||||||
if (shdr.get_sh_type() == elfcpp::SHT_NOBITS)
|
if (shdr.get_sh_type() == elfcpp::SHT_NOBITS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (parameters->output_is_object()
|
if ((parameters->output_is_object() || parameters->emit_relocs())
|
||||||
&& (shdr.get_sh_type() == elfcpp::SHT_REL
|
&& (shdr.get_sh_type() == elfcpp::SHT_REL
|
||||||
|| shdr.get_sh_type() == elfcpp::SHT_RELA)
|
|| shdr.get_sh_type() == elfcpp::SHT_RELA)
|
||||||
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
|
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
|
||||||
{
|
{
|
||||||
// This is a reloc section in a relocatable link. We don't
|
// This is a reloc section in a relocatable link or when
|
||||||
// need to read the input file. The size and file offset
|
// emitting relocs. We don't need to read the input file.
|
||||||
// are stored in the Relocatable_relocs structure.
|
// The size and file offset are stored in the
|
||||||
|
// Relocatable_relocs structure.
|
||||||
Relocatable_relocs* rr = this->relocatable_relocs(i);
|
Relocatable_relocs* rr = this->relocatable_relocs(i);
|
||||||
gold_assert(rr != NULL);
|
gold_assert(rr != NULL);
|
||||||
Output_data* posd = rr->output_data();
|
Output_data* posd = rr->output_data();
|
||||||
@ -670,15 +774,25 @@ Sized_relobj<size, big_endian>::relocate_sections(
|
|||||||
relinfo.reloc_shndx = i;
|
relinfo.reloc_shndx = i;
|
||||||
relinfo.data_shndx = index;
|
relinfo.data_shndx = index;
|
||||||
if (!parameters->output_is_object())
|
if (!parameters->output_is_object())
|
||||||
target->relocate_section(&relinfo,
|
{
|
||||||
sh_type,
|
target->relocate_section(&relinfo,
|
||||||
prelocs,
|
sh_type,
|
||||||
reloc_count,
|
prelocs,
|
||||||
os,
|
reloc_count,
|
||||||
output_offset == -1,
|
os,
|
||||||
(*pviews)[index].view,
|
output_offset == -1,
|
||||||
(*pviews)[index].address,
|
(*pviews)[index].view,
|
||||||
(*pviews)[index].view_size);
|
(*pviews)[index].address,
|
||||||
|
(*pviews)[index].view_size);
|
||||||
|
if (parameters->emit_relocs())
|
||||||
|
this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
|
||||||
|
os, output_offset,
|
||||||
|
(*pviews)[index].view,
|
||||||
|
(*pviews)[index].address,
|
||||||
|
(*pviews)[index].view_size,
|
||||||
|
(*pviews)[i].view,
|
||||||
|
(*pviews)[i].view_size);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Relocatable_relocs* rr = this->relocatable_relocs(i);
|
Relocatable_relocs* rr = this->relocatable_relocs(i);
|
||||||
@ -698,6 +812,75 @@ Sized_relobj<size, big_endian>::relocate_sections(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit the relocs for --emit-relocs.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Sized_relobj<size, big_endian>::emit_relocs(
|
||||||
|
const Relocate_info<size, big_endian>* relinfo,
|
||||||
|
unsigned int i,
|
||||||
|
unsigned int sh_type,
|
||||||
|
const unsigned char* prelocs,
|
||||||
|
size_t reloc_count,
|
||||||
|
Output_section* output_section,
|
||||||
|
off_t offset_in_output_section,
|
||||||
|
unsigned char* view,
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_Addr address,
|
||||||
|
section_size_type view_size,
|
||||||
|
unsigned char* reloc_view,
|
||||||
|
section_size_type reloc_view_size)
|
||||||
|
{
|
||||||
|
if (sh_type == elfcpp::SHT_REL)
|
||||||
|
this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs,
|
||||||
|
reloc_count, output_section,
|
||||||
|
offset_in_output_section,
|
||||||
|
view, address, view_size,
|
||||||
|
reloc_view, reloc_view_size);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||||
|
this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs,
|
||||||
|
reloc_count, output_section,
|
||||||
|
offset_in_output_section,
|
||||||
|
view, address, view_size,
|
||||||
|
reloc_view, reloc_view_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the relocs for --emit-relocs, templatized on the type of the
|
||||||
|
// relocation section.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
template<int sh_type>
|
||||||
|
void
|
||||||
|
Sized_relobj<size, big_endian>::emit_relocs_reltype(
|
||||||
|
const Relocate_info<size, big_endian>* relinfo,
|
||||||
|
unsigned int i,
|
||||||
|
const unsigned char* prelocs,
|
||||||
|
size_t reloc_count,
|
||||||
|
Output_section* output_section,
|
||||||
|
off_t offset_in_output_section,
|
||||||
|
unsigned char* view,
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_Addr address,
|
||||||
|
section_size_type view_size,
|
||||||
|
unsigned char* reloc_view,
|
||||||
|
section_size_type reloc_view_size)
|
||||||
|
{
|
||||||
|
const Relocatable_relocs* rr = this->relocatable_relocs(i);
|
||||||
|
relocate_for_relocatable<size, big_endian, sh_type>(
|
||||||
|
relinfo,
|
||||||
|
prelocs,
|
||||||
|
reloc_count,
|
||||||
|
output_section,
|
||||||
|
offset_in_output_section,
|
||||||
|
rr,
|
||||||
|
view,
|
||||||
|
address,
|
||||||
|
view_size,
|
||||||
|
reloc_view,
|
||||||
|
reloc_view_size);
|
||||||
|
}
|
||||||
|
|
||||||
// Create merge hash tables for the local symbols. These are used to
|
// Create merge hash tables for the local symbols. These are used to
|
||||||
// speed up relocations.
|
// speed up relocations.
|
||||||
|
|
||||||
|
@ -194,6 +194,9 @@ class Relocatable_relocs
|
|||||||
// SHT_RELA reloc and the contents of the data section do not need
|
// SHT_RELA reloc and the contents of the data section do not need
|
||||||
// to be changed.
|
// to be changed.
|
||||||
RELOC_ADJUST_FOR_SECTION_RELA,
|
RELOC_ADJUST_FOR_SECTION_RELA,
|
||||||
|
// Like RELOC_ADJUST_FOR_SECTION_RELA but the addend should not be
|
||||||
|
// adjusted.
|
||||||
|
RELOC_ADJUST_FOR_SECTION_0,
|
||||||
// Like RELOC_ADJUST_FOR_SECTION_RELA but the contents of the
|
// Like RELOC_ADJUST_FOR_SECTION_RELA but the contents of the
|
||||||
// section need to be changed. The number indicates the number of
|
// section need to be changed. The number indicates the number of
|
||||||
// bytes in the addend in the section contents.
|
// bytes in the addend in the section contents.
|
||||||
|
@ -256,7 +256,7 @@ class Default_scan_relocatable_relocs
|
|||||||
switch (classify.get_size_for_reloc(r_type, object))
|
switch (classify.get_size_for_reloc(r_type, object))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return Relocatable_relocs::RELOC_COPY;
|
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
|
||||||
case 1:
|
case 1:
|
||||||
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1;
|
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1;
|
||||||
case 2:
|
case 2:
|
||||||
@ -286,7 +286,7 @@ class Default_scan_relocatable_relocs
|
|||||||
// local_section_strategy. Most targets should be able to use
|
// local_section_strategy. Most targets should be able to use
|
||||||
// Default_scan_relocatable_relocs as this class.
|
// Default_scan_relocatable_relocs as this class.
|
||||||
|
|
||||||
template<int size, bool big_endian, typename Target_type, int sh_type,
|
template<int size, bool big_endian, int sh_type,
|
||||||
typename Scan_relocatable_reloc>
|
typename Scan_relocatable_reloc>
|
||||||
void
|
void
|
||||||
scan_relocatable_relocs(
|
scan_relocatable_relocs(
|
||||||
@ -365,7 +365,7 @@ scan_relocatable_relocs(
|
|||||||
// Relocate relocs during a relocatable link. This is a default
|
// Relocate relocs during a relocatable link. This is a default
|
||||||
// definition which should work for most targets.
|
// definition which should work for most targets.
|
||||||
|
|
||||||
template<int size, bool big_endian, typename Target_type, int sh_type>
|
template<int size, bool big_endian, int sh_type>
|
||||||
void
|
void
|
||||||
relocate_for_relocatable(
|
relocate_for_relocatable(
|
||||||
const Relocate_info<size, big_endian>* relinfo,
|
const Relocate_info<size, big_endian>* relinfo,
|
||||||
@ -416,6 +416,7 @@ relocate_for_relocatable(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
|
||||||
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
|
||||||
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
|
||||||
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
|
||||||
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
|
||||||
@ -503,6 +504,9 @@ relocate_for_relocatable(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
|
||||||
|
break;
|
||||||
|
|
||||||
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
|
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
|
||||||
Relocate_functions<size, big_endian>::rel8(padd, object,
|
Relocate_functions<size, big_endian>::rel8(padd, object,
|
||||||
psymval);
|
psymval);
|
||||||
|
@ -2087,7 +2087,7 @@ Target_x86_64::scan_relocatable_relocs(const General_options& options,
|
|||||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
|
||||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||||
|
|
||||||
gold::scan_relocatable_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
|
gold::scan_relocatable_relocs<64, false, elfcpp::SHT_RELA,
|
||||||
Scan_relocatable_relocs>(
|
Scan_relocatable_relocs>(
|
||||||
options,
|
options,
|
||||||
symtab,
|
symtab,
|
||||||
@ -2122,7 +2122,7 @@ Target_x86_64::relocate_for_relocatable(
|
|||||||
{
|
{
|
||||||
gold_assert(sh_type == elfcpp::SHT_RELA);
|
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||||
|
|
||||||
gold::relocate_for_relocatable<64, false, Target_x86_64, elfcpp::SHT_RELA>(
|
gold::relocate_for_relocatable<64, false, elfcpp::SHT_RELA>(
|
||||||
relinfo,
|
relinfo,
|
||||||
prelocs,
|
prelocs,
|
||||||
reloc_count,
|
reloc_count,
|
||||||
|
Reference in New Issue
Block a user