// aarch64.cc -- aarch64 target support for gold.
-// Copyright (C) 2014-2017 Free Software Foundation, Inc.
+// Copyright (C) 2014-2020 Free Software Foundation, Inc.
// Written by Jing Yu <jingyu@google.com> and Han Shen <shenhan@google.com>.
// This file is part of gold.
set_erratum_address(AArch64_address addr)
{ this->erratum_address_ = addr; }
+ // Later relaxation passes of may alter the recorded erratum and destination
+ // address. Given an up to date output section address of shidx_ in
+ // relobj_ we can derive the erratum_address and destination address.
+ void
+ update_erratum_address(AArch64_address output_section_addr)
+ {
+ const int BPI = AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
+ AArch64_address updated_addr = output_section_addr + this->sh_offset_;
+ this->set_erratum_address(updated_addr);
+ this->set_destination_address(updated_addr + BPI);
+ }
+
// Comparator used to group Erratum_stubs in a set by (obj, shndx,
// sh_offset). We do not include 'type' in the calculation, because there is
// at most one stub type at (obj, shndx, sh_offset).
void
invalidate_erratum_stub()
{
- gold_assert(this->relobj_ != NULL);
- this->relobj_ = NULL;
+ gold_assert(this->erratum_insn_ != invalid_insn);
+ this->erratum_insn_ = invalid_insn;
}
bool
is_invalidated_erratum_stub()
- { return this->relobj_ == NULL; }
+ { return this->erratum_insn_ == invalid_insn; }
protected:
virtual void
output_address = poris->address();
}
+ // Update the addresses in previously generated erratum stubs. Unlike when
+ // we scan relocations for stubs, if section addresses have changed due to
+ // other relaxations we are unlikely to scan the same erratum instances
+ // again.
+ The_stub_table* stub_table = this->stub_table(shndx);
+ if (stub_table)
+ {
+ std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter>
+ ipair(stub_table->find_erratum_stubs_for_input_section(this, shndx));
+ for (Erratum_stub_set_iter p = ipair.first; p != ipair.second; ++p)
+ (*p)->update_erratum_address(output_address);
+ }
+
section_size_type input_view_size = 0;
const unsigned char* input_view =
this->section_contents(shndx, &input_view_size, false);
NULL, // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
template<>
NULL, // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
template<>
NULL, // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
template<>
NULL, // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
// Get the GOT section, creating it if necessary.
const Symbol_value<size> *psymval;
bool is_defined_in_discarded_section;
unsigned int shndx;
+ const Symbol* gsym = NULL;
if (r_sym < local_count)
{
sym = NULL;
}
else
{
- const Symbol* gsym;
gsym = object->global_symbol(r_sym);
gold_assert(gsym != NULL);
if (gsym->is_forwarder())
Symbol_value<size> symval2;
if (is_defined_in_discarded_section)
{
+ std::string name = object->section_name(relinfo->data_shndx);
+
if (comdat_behavior == CB_UNDETERMINED)
- {
- std::string name = object->section_name(relinfo->data_shndx);
comdat_behavior = default_comdat_behavior.get(name.c_str());
- }
+
if (comdat_behavior == CB_PRETEND)
{
bool found;
typename elfcpp::Elf_types<size>::Elf_Addr value =
- object->map_to_kept_section(shndx, &found);
+ object->map_to_kept_section(shndx, name, &found);
if (found)
symval2.set_output_value(value + psymval->input_value());
else
}
else
{
- if (comdat_behavior == CB_WARNING)
- gold_warning_at_location(relinfo, i, offset,
- _("relocation refers to discarded "
- "section"));
+ if (comdat_behavior == CB_ERROR)
+ issue_discarded_error(relinfo, i, offset, r_sym, gsym);
symval2.set_output_value(0);
}
symval2.set_no_output_symtab_entry();
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
// When we already have Local-Exec, there is nothing further we
// can do.
return tls::TLSOPT_NONE;
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
{
layout->set_has_static_tls();
bool output_is_shared = parameters->options().shared();
gold_error(_("%s: unsupported reloc %u in pos independent link."),
object->name().c_str(), r_type);
}
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
break;
case elfcpp::R_AARCH64_LD_PREL_LO19: // 273
case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
- case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: // Local executable
+ case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: // Local executable
layout->set_has_static_tls();
if (parameters->options().shared())
gold_error(_("%s: unsupported TLSLE reloc type %u in shared objects."),
}
// Set the size of the _GLOBAL_OFFSET_TABLE_ symbol to the size of
- // the .got.plt section.
+ // the .got section.
Symbol* sym = this->global_offset_table_;
if (sym != NULL)
{
- uint64_t data_size = this->got_plt_->current_data_size();
+ uint64_t data_size = this->got_->current_data_size();
symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
// If the .got section is more than 0x8000 bytes, we add
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
{
gold_assert(tls_segment != NULL);
AArch64_address value = psymval->value(object, 0);