#include "target-select.h"
#include "tls.h"
#include "errors.h"
+#include "gc.h"
namespace
{
// Process the relocations to determine unreferenced sections for
// garbage collection.
void
- gc_process_relocs(const General_options& options,
- Symbol_table* symtab,
+ gc_process_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
unsigned int data_shndx,
// Scan the relocations to look for symbol adjustments.
void
- scan_relocs(const General_options& options,
- Symbol_table* symtab,
+ scan_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
unsigned int data_shndx,
const unsigned char* plocal_symbols);
// Finalize the sections.
void
- do_finalize_sections(Layout*);
+ do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
// Return the value to use for a dynamic which requires special
// treatment.
bool needs_special_offset_handling,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
- section_size_type view_size);
+ section_size_type view_size,
+ const Reloc_symbol_changes*);
// Scan the relocs during a relocatable link.
void
- scan_relocatable_relocs(const General_options& options,
- Symbol_table* symtab,
+ scan_relocatable_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
unsigned int data_shndx,
{ }
inline void
- local(const General_options& options, Symbol_table* symtab,
- Layout* layout, Target_sparc* target,
+ local(Symbol_table* symtab, Layout* layout, Target_sparc* target,
Sized_relobj<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
const elfcpp::Sym<size, big_endian>& lsym);
inline void
- global(const General_options& options, Symbol_table* symtab,
- Layout* layout, Target_sparc* target,
+ global(Symbol_table* symtab, Layout* layout, Target_sparc* target,
Sized_relobj<size, big_endian>* object,
unsigned int data_shndx,
Output_section* output_section,
Reloc_section*
rela_dyn_section(Layout*);
- // Return true if the symbol may need a COPY relocation.
- // References from an executable object to non-function symbols
- // defined in a dynamic object may need a COPY relocation.
- bool
- may_need_copy_reloc(Symbol* gsym)
- {
- return (!parameters->options().shared()
- && gsym->is_from_dynobj()
- && gsym->type() != elfcpp::STT_FUNC);
- }
-
// Copy a relocation against a global symbol.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
"/usr/lib/ld.so.1", // dynamic_linker
0x00010000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
- 8 * 1024 // common_pagesize (overridable by -z common-page-size)
+ 8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_UNDEF, // large_common_shndx
+ 0, // small_common_section_flags
+ 0, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
};
template<>
"/usr/lib/sparcv9/ld.so.1", // dynamic_linker
0x100000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
- 8 * 1024 // common_pagesize (overridable by -z common-page-size)
+ 8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_UNDEF, // large_common_shndx
+ 0, // small_common_section_flags
+ 0, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
};
// We have to take care here, even when operating in little-endian
rela(unsigned char* view,
unsigned int right_shift,
typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask,
- typename elfcpp::Swap<size, big_endian>::Valtype value,
+ typename elfcpp::Swap<size, big_endian>::Valtype avalue,
typename elfcpp::Swap<size, big_endian>::Valtype addend)
{
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv);
- Valtype reloc = ((value + addend) >> right_shift);
+ Valtype reloc = ((avalue + addend) >> right_shift);
val &= ~dst_mask;
reloc &= dst_mask;
// R_SPARC_HI22: (Symbol + Addend) >> 10
static inline void
hi22(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
- This_insn::template rela<32>(view, 10, 0x003fffff, value, addend);
+ This_insn::template rela<32>(view, 10, 0x003fffff, avalue, addend);
}
// R_SPARC_HI22: (Symbol + Addend) >> 10
// R_SPARC_LO10: (Symbol + Addend) & 0x3ff
static inline void
lo10(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
- This_insn::template rela<32>(view, 0, 0x000003ff, value, addend);
+ This_insn::template rela<32>(view, 0, 0x000003ff, avalue, addend);
}
// R_SPARC_LO10: (Symbol + Addend) & 0x3ff
// R_SPARC_13: (Symbol + Addend)
static inline void
rela32_13(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
- This_insn::template rela<32>(view, 0, 0x00001fff, value, addend);
+ This_insn::template rela<32>(view, 0, 0x00001fff, avalue, addend);
}
// R_SPARC_13: (Symbol + Addend)
// R_SPARC_TLS_LDO_HIX22: @dtpoff(Symbol + Addend) >> 10
static inline void
ldo_hix22(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
- This_insn::hi22(view, value, addend);
+ This_insn::hi22(view, avalue, addend);
}
// R_SPARC_TLS_LDO_LOX10: @dtpoff(Symbol + Addend) & 0x3ff
static inline void
ldo_lox10(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<32, true>::readval(wv);
- Valtype reloc = (value + addend);
+ Valtype reloc = (avalue + addend);
val &= ~0x1fff;
reloc &= 0x3ff;
// R_SPARC_TLS_LE_HIX22: (@tpoff(Symbol + Addend) ^ 0xffffffffffffffff) >> 10
static inline void
hix22(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<32, true>::readval(wv);
- Valtype reloc = (value + addend);
+ Valtype reloc = (avalue + addend);
val &= ~0x3fffff;
// R_SPARC_TLS_LE_LOX10: (@tpoff(Symbol + Addend) & 0x3ff) | 0x1c00
static inline void
lox10(unsigned char* view,
- typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue,
typename elfcpp::Elf_types<size>::Elf_Addr addend)
{
typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<32, true>::readval(wv);
- Valtype reloc = (value + addend);
+ Valtype reloc = (avalue + addend);
val &= ~0x1fff;
reloc &= 0x3ff;
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_);
+ this->got_, false);
os->set_is_relro();
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rela_dyn_);
+ elfcpp::SHF_ALLOC, this->rela_dyn_, true);
}
return this->rela_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
template<int size, bool big_endian>
void
Output_data_plt_sparc<size, big_endian>::do_write(Output_file* of)
{
- const off_t offset = this->offset();
+ const off_t off = this->offset();
const section_size_type oview_size =
convert_to_section_size_type(this->data_size());
- unsigned char* const oview = of->get_output_view(offset, oview_size);
+ unsigned char* const oview = of->get_output_view(off, oview_size);
unsigned char* pov = oview;
memset(pov, 0, base_plt_entry_size * 4);
gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
- of->write_output_view(offset, oview_size, oview);
+ of->write_output_view(off, oview_size, oview);
}
// Create a PLT entry for a global symbol.
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
- this->plt_);
+ this->plt_, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
// error per object file.
if (this->issued_non_pic_error_)
return;
+ gold_assert(parameters->options().output_is_position_independent());
object->error(_("requires unsupported dynamic reloc; "
"recompile with -fPIC"));
this->issued_non_pic_error_ = true;
template<int size, bool big_endian>
inline void
Target_sparc<size, big_endian>::Scan::local(
- const General_options&,
Symbol_table* symtab,
Layout* layout,
Target_sparc<size, big_endian>* target,
template<int size, bool big_endian>
inline void
Target_sparc<size, big_endian>::Scan::global(
- const General_options&,
Symbol_table* symtab,
Layout* layout,
Target_sparc<size, big_endian>* target,
flags |= Symbol::FUNCTION_CALL;
if (gsym->needs_dynamic_reloc(flags))
{
- if (target->may_need_copy_reloc(gsym))
+ if (gsym->may_need_copy_reloc())
{
target->copy_reloc(symtab, layout, object,
data_shndx, output_section, gsym,
// Make a dynamic relocation if necessary.
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
{
- if (target->may_need_copy_reloc(gsym))
+ if (gsym->may_need_copy_reloc())
{
target->copy_reloc(symtab, layout, object,
data_shndx, output_section, gsym, reloc);
template<int size, bool big_endian>
void
Target_sparc<size, big_endian>::gc_process_relocs(
- const General_options& options,
Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
const unsigned char* plocal_symbols)
{
typedef Target_sparc<size, big_endian> Sparc;
- typedef typename Target_sparc<size, big_endian>::Scan Scan;
+ typedef typename Target_sparc<size, big_endian>::Scan scan;
- gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
- options,
+ gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, scan>(
symtab,
layout,
this,
template<int size, bool big_endian>
void
Target_sparc<size, big_endian>::scan_relocs(
- const General_options& options,
Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
const unsigned char* plocal_symbols)
{
typedef Target_sparc<size, big_endian> Sparc;
- typedef typename Target_sparc<size, big_endian>::Scan Scan;
+ typedef typename Target_sparc<size, big_endian>::Scan scan;
if (sh_type == elfcpp::SHT_REL)
{
return;
}
- gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
- options,
+ gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, scan>(
symtab,
layout,
this,
template<int size, bool big_endian>
void
-Target_sparc<size, big_endian>::do_finalize_sections(Layout* layout)
+Target_sparc<size, big_endian>::do_finalize_sections(
+ Layout* layout,
+ const Input_objects*,
+ Symbol_table*)
{
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();
if (odyn != NULL)
{
- if (this->plt_ != NULL)
+ if (this->plt_ != NULL
+ && this->plt_->output_section() != NULL)
{
const Output_data* od = this->plt_->rel_plt();
odyn->add_section_size(elfcpp::DT_PLTRELSZ, od);
odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_);
}
- if (this->rela_dyn_ != NULL)
+ if (this->rela_dyn_ != NULL
+ && this->rela_dyn_->output_section() != NULL)
{
const Output_data* od = this->rela_dyn_;
odyn->add_section_address(elfcpp::DT_RELA, od);
|| r_type == elfcpp::R_SPARC_WDISP19
|| r_type == elfcpp::R_SPARC_WDISP16))
{
- elfcpp::Elf_Xword value;
+ elfcpp::Elf_Xword avalue;
- value = target->plt_section()->address() + gsym->plt_offset();
+ avalue = target->plt_section()->address() + gsym->plt_offset();
- symval.set_output_value(value);
+ symval.set_output_value(avalue);
psymval = &symval;
}
typedef typename elfcpp::Swap<32, true>::Valtype Insntype;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(object, 0);
+ typename elfcpp::Elf_types<size>::Elf_Addr avalue = psymval->value(object, 0);
const bool is_final =
(gsym == NULL
Insntype* wv = reinterpret_cast<Insntype*>(view);
Insntype val;
- value -= tls_segment->memsz();
+ avalue -= tls_segment->memsz();
switch (r_type)
{
case elfcpp::R_SPARC_TLS_GD_HI22:
// TLS_GD_HI22 --> TLS_LE_HIX22
- Reloc::hix22(view, value, addend);
+ Reloc::hix22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_LO10:
// TLS_GD_LO10 --> TLS_LE_LOX10
- Reloc::lox10(view, value, addend);
+ Reloc::lox10(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_ADD:
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
- value = gsym->got_offset(got_type);
+ avalue = gsym->got_offset(got_type);
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
- value = object->local_got_offset(r_sym, got_type);
+ avalue = object->local_got_offset(r_sym, got_type);
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
{
case elfcpp::R_SPARC_TLS_GD_HI22:
// TLS_GD_HI22 --> TLS_IE_HI22
- Reloc::hi22(view, value, addend);
+ Reloc::hi22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_LO10:
// TLS_GD_LO10 --> TLS_IE_LO10
- Reloc::lo10(view, value, addend);
+ Reloc::lo10(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_ADD:
switch (r_type)
{
case elfcpp::R_SPARC_TLS_GD_HI22:
- Reloc::hi22(view, value, addend);
+ Reloc::hi22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_LO10:
- Reloc::lo10(view, value, addend);
+ Reloc::lo10(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_GD_ADD:
break;
case elfcpp::R_SPARC_TLS_GD_CALL:
{
Symbol_value<size> symval;
- elfcpp::Elf_Xword value;
+ elfcpp::Elf_Xword xvalue;
Symbol* tsym;
tsym = target->tls_get_addr_sym_;
gold_assert(tsym);
- value = (target->plt_section()->address() +
- tsym->plt_offset());
- symval.set_output_value(value);
+ xvalue = (target->plt_section()->address() +
+ tsym->plt_offset());
+ symval.set_output_value(xvalue);
Reloc::wdisp30(view, object, &symval, addend, address);
}
break;
case elfcpp::R_SPARC_TLS_LDM_CALL:
{
Symbol_value<size> symval;
- elfcpp::Elf_Xword value;
+ elfcpp::Elf_Xword xvalue;
Symbol* tsym;
tsym = target->tls_get_addr_sym_;
gold_assert(tsym);
- value = (target->plt_section()->address() +
- tsym->plt_offset());
- symval.set_output_value(value);
+ xvalue = (target->plt_section()->address() +
+ tsym->plt_offset());
+ symval.set_output_value(xvalue);
Reloc::wdisp30(view, object, &symval, addend, address);
}
break;
case elfcpp::R_SPARC_TLS_LDO_HIX22:
if (optimized_type == tls::TLSOPT_TO_LE)
{
- value -= tls_segment->memsz();
- Reloc::hix22(view, value, addend);
+ avalue -= tls_segment->memsz();
+ Reloc::hix22(view, avalue, addend);
}
else
- Reloc::ldo_hix22(view, value, addend);
+ Reloc::ldo_hix22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_LDO_LOX10:
if (optimized_type == tls::TLSOPT_TO_LE)
{
- value -= tls_segment->memsz();
- Reloc::lox10(view, value, addend);
+ avalue -= tls_segment->memsz();
+ Reloc::lox10(view, avalue, addend);
}
else
- Reloc::ldo_lox10(view, value, addend);
+ Reloc::ldo_lox10(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_LDO_ADD:
if (optimized_type == tls::TLSOPT_TO_LE)
case elfcpp::R_SPARC_TLS_IE_LO10:
if (optimized_type == tls::TLSOPT_TO_LE)
{
- value -= tls_segment->memsz();
+ avalue -= tls_segment->memsz();
switch (r_type)
{
case elfcpp::R_SPARC_TLS_IE_HI22:
// IE_HI22 --> LE_HIX22
- Reloc::hix22(view, value, addend);
+ Reloc::hix22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_IE_LO10:
// IE_LO10 --> LE_LOX10
- Reloc::lox10(view, value, addend);
+ Reloc::lox10(view, avalue, addend);
break;
}
break;
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
- value = gsym->got_offset(GOT_TYPE_TLS_OFFSET);
+ avalue = gsym->got_offset(GOT_TYPE_TLS_OFFSET);
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym,
GOT_TYPE_TLS_OFFSET));
- value = object->local_got_offset(r_sym,
- GOT_TYPE_TLS_OFFSET);
+ avalue = object->local_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET);
}
switch (r_type)
{
case elfcpp::R_SPARC_TLS_IE_HI22:
- Reloc::hi22(view, value, addend);
+ Reloc::hi22(view, avalue, addend);
break;
case elfcpp::R_SPARC_TLS_IE_LO10:
- Reloc::lo10(view, value, addend);
+ Reloc::lo10(view, avalue, addend);
break;
}
break;
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
{
- value -= tls_segment->memsz();
- Reloc::hix22(view, value, addend);
+ avalue -= tls_segment->memsz();
+ Reloc::hix22(view, avalue, addend);
}
break;
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
{
- value -= tls_segment->memsz();
- Reloc::lox10(view, value, addend);
+ avalue -= tls_segment->memsz();
+ Reloc::lox10(view, avalue, addend);
}
break;
}
bool needs_special_offset_handling,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr address,
- section_size_type view_size)
+ section_size_type view_size,
+ const Reloc_symbol_changes* reloc_symbol_changes)
{
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate;
needs_special_offset_handling,
view,
address,
- view_size);
+ view_size,
+ reloc_symbol_changes);
}
// Return the size of a relocation while scanning during a relocatable
template<int size, bool big_endian>
void
Target_sparc<size, big_endian>::scan_relocatable_relocs(
- const General_options& options,
Symbol_table* symtab,
Layout* layout,
Sized_relobj<size, big_endian>* object,
gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA,
Scan_relocatable_relocs>(
- options,
symtab,
layout,
object,
(size == 64 ? "elf64-sparc" : "elf32-sparc"))
{ }
- Target* do_recognize(int machine, int, int)
+ Target* do_recognize(int amachine, int, int)
{
switch (size)
{
case 64:
- if (machine != elfcpp::EM_SPARCV9)
+ if (amachine != elfcpp::EM_SPARCV9)
return NULL;
break;
case 32:
- if (machine != elfcpp::EM_SPARC
- && machine != elfcpp::EM_SPARC32PLUS)
+ if (amachine != elfcpp::EM_SPARC
+ && amachine != elfcpp::EM_SPARC32PLUS)
return NULL;
break;