// Return whether SYM is defined by the ABI.
bool
- do_is_defined_by_abi(Symbol* sym) const
+ do_is_defined_by_abi(const Symbol* sym) const
{ return strcmp(sym->name(), "___tls_get_addr") == 0; }
// Return the size of the GOT section.
void
make_plt_entry(Symbol_table*, Layout*, Symbol*);
- // Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment.
+ // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
void
define_tls_base_symbol(Symbol_table*, Layout*);
// Add a potential copy relocation.
void
- copy_reloc(Symbol_table* symtab, Layout* layout, Relobj* object,
+ copy_reloc(Symbol_table* symtab, Layout* layout,
+ Sized_relobj<32, false>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rel<32, false>& reloc)
{
this->got_ = new Output_data_got<32, false>();
- layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->got_);
+ Output_section* os;
+ os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_);
+ os->set_is_relro();
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
- this->got_plt_ = new Output_data_space(4);
- layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->got_plt_);
+ this->got_plt_ = new Output_data_space(4, "** GOT PLT");
+ os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_plt_);
+ os->set_is_relro();
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
if (this->rel_dyn_ == NULL)
{
gold_assert(layout != NULL);
- this->rel_dyn_ = new Reloc_section();
+ this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
elfcpp::SHF_ALLOC, this->rel_dyn_);
}
void
do_adjust_output_section(Output_section* os);
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, _("** PLT")); }
+
private:
// The size of an entry in the PLT.
static const int plt_entry_size = 16;
Output_data_space* got_plt)
: Output_section_data(4), got_plt_(got_plt), count_(0)
{
- this->rel_ = new Reloc_section();
+ this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
elfcpp::SHF_ALLOC, this->rel_);
}
this->plt_->add_entry(gsym);
}
-// Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment.
+// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
void
Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
Output_segment* tls_segment = layout->tls_segment();
if (tls_segment != NULL)
{
+ bool is_exec = parameters->options().output_is_executable();
symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL,
tls_segment, 0, 0,
elfcpp::STT_TLS,
elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
- Symbol::SEGMENT_END, true);
+ (is_exec
+ ? Symbol::SEGMENT_END
+ : Symbol::SEGMENT_START),
+ true);
}
this->tls_base_symbol_defined_ = true;
}
// Pick the value to use for symbols defined in shared objects.
Symbol_value<32> symval;
- bool is_nonpic = (r_type == elfcpp::R_386_PC8
- || r_type == elfcpp::R_386_PC16
- || r_type == elfcpp::R_386_PC32);
if (gsym != NULL
- && (gsym->is_from_dynobj()
- || (parameters->options().shared()
- && (gsym->is_undefined() || gsym->is_preemptible())))
- && gsym->has_plt_offset()
- && (!is_nonpic || !parameters->options().shared()))
+ && gsym->use_plt_offset(r_type == elfcpp::R_386_PC8
+ || r_type == elfcpp::R_386_PC16
+ || r_type == elfcpp::R_386_PC32))
{
symval.set_output_value(target->plt_section()->address()
+ gsym->plt_offset());
if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC)
ref_flags |= Symbol::FUNCTION_CALL;
if (should_apply_static_reloc(gsym, ref_flags, false))
- Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
+ Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
}
break;
if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC)
ref_flags |= Symbol::FUNCTION_CALL;
if (should_apply_static_reloc(gsym, ref_flags, false))
- Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
+ Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
}
break;
case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_386_TLS_DESC_CALL:
+ this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
// This reloc can appear in debugging sections, in which case we
// won't see the TLS_LDM reloc. The local_dynamic_type field
// tells us this.
- if (optimized_type == tls::TLSOPT_TO_LE)
+ if (optimized_type == tls::TLSOPT_TO_LE
+ && this->local_dynamic_type_ != LOCAL_DYNAMIC_NONE)
{
gold_assert(tls_segment != NULL);
value -= tls_segment->memsz();