// compilation time and generate a representation of it in PODs only. That
// way we can avoid initialization when the linker starts.
-Arm_reloc_property_table *arm_reloc_property_table = NULL;
+Arm_reloc_property_table* arm_reloc_property_table = NULL;
// Instruction template class. This class is similar to the insn_sequence
// struct in bfd/elf32-arm.c.
this->do_fixed_endian_write<false>(of);
}
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, _("** ARM cantunwind")); }
+
private:
// Implement do_write for a given endianness.
template<bool big_endian>
void
do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
- const unsigned char* pshdrs,
+ const unsigned char* pshdrs, Output_file* of,
typename Sized_relobj<32, big_endian>::Views* pivews);
// Read the symbol information.
bool
section_needs_reloc_stub_scanning(const elfcpp::Shdr<32, big_endian>&,
const Relobj::Output_sections&,
- const Symbol_table *, const unsigned char*);
+ const Symbol_table*, const unsigned char*);
// Whether a section is a scannable text section.
bool
section_is_scannable(const elfcpp::Shdr<32, big_endian>&, unsigned int,
- const Output_section*, const Symbol_table *);
+ const Output_section*, const Symbol_table*);
// Whether a section needs to be scanned for the Cortex-A8 erratum.
bool
section_needs_cortex_a8_stub_scanning(const elfcpp::Shdr<32, big_endian>&,
unsigned int, Output_section*,
- const Symbol_table *);
+ const Symbol_table*);
// Scan a section for the Cortex-A8 erratum.
void
// Map platform-specific reloc types
static unsigned int
- get_real_reloc_type (unsigned int r_type);
+ get_real_reloc_type(unsigned int r_type);
//
// Methods to support stub-generations.
// reloc. This means the relocation type accesses a symbol not via
// GOT or PLT.
static inline bool
- reloc_is_non_pic (unsigned int r_type)
+ reloc_is_non_pic(unsigned int r_type)
{
switch (r_type)
{
// Handle ARM long branches.
static typename This::Status
arm_branch_common(unsigned int, const Relocate_info<32, big_endian>*,
- unsigned char *, const Sized_symbol<32>*,
+ unsigned char*, const Sized_symbol<32>*,
const Arm_relobj<big_endian>*, unsigned int,
const Symbol_value<32>*, Arm_address, Arm_address, bool);
// Handle THUMB long branches.
static typename This::Status
thumb_branch_common(unsigned int, const Relocate_info<32, big_endian>*,
- unsigned char *, const Sized_symbol<32>*,
+ unsigned char*, const Sized_symbol<32>*,
const Arm_relobj<big_endian>*, unsigned int,
const Symbol_value<32>*, Arm_address, Arm_address, bool);
// R_ARM_ABS8: S + A
static inline typename This::Status
- abs8(unsigned char *view,
+ abs8(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
// R_ARM_THM_ABS5: S + A
static inline typename This::Status
- thm_abs5(unsigned char *view,
+ thm_abs5(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
// R_ARM_ABS12: S + A
static inline typename This::Status
- abs12(unsigned char *view,
+ abs12(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
// R_ARM_ABS16: S + A
static inline typename This::Status
- abs16(unsigned char *view,
+ abs16(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
// R_ARM_ABS32: (S + A) | T
static inline typename This::Status
- abs32(unsigned char *view,
+ abs32(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address thumb_bit)
// R_ARM_REL32: (S + A) | T - P
static inline typename This::Status
- rel32(unsigned char *view,
+ rel32(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address,
// R_ARM_THM_JUMP24: (S + A) | T - P
static typename This::Status
- thm_jump19(unsigned char *view, const Arm_relobj<big_endian>* object,
+ thm_jump19(unsigned char* view, const Arm_relobj<big_endian>* object,
const Symbol_value<32>* psymval, Arm_address address,
Arm_address thumb_bit);
// R_ARM_THM_JUMP6: S + A – P
static inline typename This::Status
- thm_jump6(unsigned char *view,
+ thm_jump6(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address)
// R_ARM_THM_JUMP8: S + A – P
static inline typename This::Status
- thm_jump8(unsigned char *view,
+ thm_jump8(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address)
// R_ARM_THM_JUMP11: S + A – P
static inline typename This::Status
- thm_jump11(unsigned char *view,
+ thm_jump11(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address)
// R_ARM_GOT_PREL: GOT(S) + A - P
static inline typename This::Status
- got_prel(unsigned char *view,
+ got_prel(unsigned char* view,
Arm_address got_entry,
Arm_address address)
{
// R_ARM_PREL: (S + A) | T - P
static inline typename This::Status
- prel31(unsigned char *view,
+ prel31(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address,
// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
static inline typename This::Status
- thm_movw(unsigned char *view,
+ thm_movw(unsigned char* view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address relative_address_base,
// R_ARM_V4BX
static inline typename This::Status
v4bx(const Relocate_info<32, big_endian>* relinfo,
- unsigned char *view,
+ unsigned char* view,
const Arm_relobj<big_endian>* object,
const Arm_address address,
const bool is_interworking)
Arm_relocate_functions<big_endian>::arm_branch_common(
unsigned int r_type,
const Relocate_info<32, big_endian>* relinfo,
- unsigned char *view,
+ unsigned char* view,
const Sized_symbol<32>* gsym,
const Arm_relobj<big_endian>* object,
unsigned int r_sym,
Arm_relocate_functions<big_endian>::thumb_branch_common(
unsigned int r_type,
const Relocate_info<32, big_endian>* relinfo,
- unsigned char *view,
+ unsigned char* view,
const Sized_symbol<32>* gsym,
const Arm_relobj<big_endian>* object,
unsigned int r_sym,
template<bool big_endian>
typename Arm_relocate_functions<big_endian>::Status
Arm_relocate_functions<big_endian>::thm_jump19(
- unsigned char *view,
+ unsigned char* view,
const Arm_relobj<big_endian>* object,
const Symbol_value<32>* psymval,
Arm_address address,
const elfcpp::Shdr<32, big_endian>& shdr,
unsigned int shndx,
const Output_section* os,
- const Symbol_table *symtab)
+ const Symbol_table* symtab)
{
// Skip any empty sections, unallocated sections or sections whose
// type are not SHT_PROGBITS.
Arm_relobj<big_endian>::section_needs_reloc_stub_scanning(
const elfcpp::Shdr<32, big_endian>& shdr,
const Relobj::Output_sections& out_sections,
- const Symbol_table *symtab,
+ const Symbol_table* symtab,
const unsigned char* pshdrs)
{
unsigned int sh_type = shdr.get_sh_type();
const Symbol_table* symtab,
const Layout* layout,
const unsigned char* pshdrs,
+ Output_file* of,
typename Sized_relobj<32, big_endian>::Views* pviews)
{
// Call parent to relocate sections.
Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs,
- pviews);
+ of, pviews);
// We do not generate stubs if doing a relocatable link.
if (parameters->options().relocatable())
std::vector<unsigned int> deferred_exidx_sections;
const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
const unsigned char* pshdrs = sd->section_headers->data();
- const unsigned char *ps = pshdrs + shdr_size;
+ const unsigned char* ps = pshdrs + shdr_size;
bool must_merge_flags_and_attributes = false;
for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size)
{
// We read from the end because gas seems to put it near the end of
// the section headers.
const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
- const unsigned char *ps =
+ const unsigned char* ps =
sd->section_headers->data() + shdr_size * (this->shnum() - 1);
for (unsigned int i = this->shnum(); i > 0; --i, ps -= shdr_size)
{
// Handle the .ARM.exidx section.
Output_section* exidx_section = layout->find_output_section(".ARM.exidx");
- if (exidx_section != NULL
- && exidx_section->type() == elfcpp::SHT_ARM_EXIDX
- && !parameters->options().relocatable())
- {
- // Create __exidx_start and __exdix_end symbols.
- symtab->define_in_output_data("__exidx_start", NULL,
- Symbol_table::PREDEFINED,
- exidx_section, 0, 0, elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
- false, true);
- symtab->define_in_output_data("__exidx_end", NULL,
- Symbol_table::PREDEFINED,
- exidx_section, 0, 0, elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
- true, true);
- // For the ARM target, we need to add a PT_ARM_EXIDX segment for
- // the .ARM.exidx section.
- if (!layout->script_options()->saw_phdrs_clause())
- {
- gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0, 0)
- == NULL);
- Output_segment* exidx_segment =
- layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
- exidx_segment->add_output_section_to_nonload(exidx_section,
- elfcpp::PF_R);
- }
+ if (!parameters->options().relocatable())
+ {
+ if (exidx_section != NULL
+ && exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
+ {
+ // Create __exidx_start and __exdix_end symbols.
+ symtab->define_in_output_data("__exidx_start", NULL,
+ Symbol_table::PREDEFINED,
+ exidx_section, 0, 0, elfcpp::STT_OBJECT,
+ elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN,
+ 0, false, true);
+ symtab->define_in_output_data("__exidx_end", NULL,
+ Symbol_table::PREDEFINED,
+ exidx_section, 0, 0, elfcpp::STT_OBJECT,
+ elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN,
+ 0, true, true);
+
+ // For the ARM target, we need to add a PT_ARM_EXIDX segment for
+ // the .ARM.exidx section.
+ if (!layout->script_options()->saw_phdrs_clause())
+ {
+ gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0,
+ 0)
+ == NULL);
+ Output_segment* exidx_segment =
+ layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
+ exidx_segment->add_output_section_to_nonload(exidx_section,
+ elfcpp::PF_R);
+ }
+ }
+ else
+ {
+ symtab->define_as_constant("__exidx_start", NULL,
+ Symbol_table::PREDEFINED,
+ 0, 0, elfcpp::STT_OBJECT,
+ elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
+ true, false);
+ symtab->define_as_constant("__exidx_end", NULL,
+ Symbol_table::PREDEFINED,
+ 0, 0, elfcpp::STT_OBJECT,
+ elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
+ true, false);
+ }
}
// Create an .ARM.attributes section if we have merged any attributes
Target_arm<big_endian>::Relocate::relocate(
const Relocate_info<32, big_endian>* relinfo,
Target_arm* target,
- Output_section *output_section,
+ Output_section* output_section,
size_t relnum,
const elfcpp::Rel<32, big_endian>& rel,
unsigned int r_type,
//
template<bool big_endian>
unsigned int
-Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
+Target_arm<big_endian>::get_real_reloc_type(unsigned int r_type)
{
switch (r_type)
{
Target_arm<big_endian>::get_secondary_compatible_arch(
const Attributes_section_data* pasd)
{
- const Object_attribute *known_attributes =
+ const Object_attribute* known_attributes =
pasd->known_attributes(Object_attribute::OBJ_ATTR_PROC);
// Note: the tag and its argument below are uleb128 values, though
Attributes_section_data* pasd,
int arch)
{
- Object_attribute *known_attributes =
+ Object_attribute* known_attributes =
pasd->known_attributes(Object_attribute::OBJ_ATTR_PROC);
if (arch == -1)
T(V7E_M), // V7E_M.
T(V4T_PLUS_V6_M) // V4T plus V6_M.
};
- static const int *comb[] =
+ static const int* comb[] =
{
v6t2,
v6k,
std::string
Target_arm<big_endian>::aeabi_enum_name(unsigned int value)
{
- static const char *aeabi_enum_names[] =
+ static const char* aeabi_enum_names[] =
{ "", "variable-size", "32-bit", "" };
const size_t aeabi_enum_names_size =
sizeof(aeabi_enum_names) / sizeof(aeabi_enum_names[0]);
std::string
Target_arm<big_endian>::tag_cpu_name_value(unsigned int value)
{
- static const char *name_table[] = {
+ static const char* name_table[] = {
// These aren't real CPU names, but we can't guess
// that from the architecture version alone.
"Pre v4",
Symbol_value<32> symval;
const Symbol_value<32> *psymval;
+ bool is_defined_in_discarded_section;
+ unsigned int shndx;
if (r_sym < local_count)
{
sym = NULL;
// counterpart in the kept section. The symbol must not
// correspond to a section we are folding.
bool is_ordinary;
- unsigned int shndx = psymval->input_shndx(&is_ordinary);
- if (is_ordinary
- && shndx != elfcpp::SHN_UNDEF
- && !arm_object->is_section_included(shndx)
- && !(relinfo->symtab->is_section_folded(arm_object, shndx)))
+ shndx = psymval->input_shndx(&is_ordinary);
+ is_defined_in_discarded_section =
+ (is_ordinary
+ && shndx != elfcpp::SHN_UNDEF
+ && !arm_object->is_section_included(shndx)
+ && !relinfo->symtab->is_section_folded(arm_object, shndx));
+
+ // We need to compute the would-be final value of this local
+ // symbol.
+ if (!is_defined_in_discarded_section)
{
- if (comdat_behavior == CB_UNDETERMINED)
- {
- std::string name =
- arm_object->section_name(relinfo->data_shndx);
- comdat_behavior = get_comdat_behavior(name.c_str());
- }
- if (comdat_behavior == CB_PRETEND)
- {
- bool found;
- typename elfcpp::Elf_types<32>::Elf_Addr value =
- arm_object->map_to_kept_section(shndx, &found);
- if (found)
- symval.set_output_value(value + psymval->input_value());
- else
- symval.set_output_value(0);
- }
+ typedef Sized_relobj<32, big_endian> ObjType;
+ typename ObjType::Compute_final_local_value_status status =
+ arm_object->compute_final_local_value(r_sym, psymval, &symval,
+ relinfo->symtab);
+ if (status == ObjType::CFLV_OK)
+ {
+ // Currently we cannot handle a branch to a target in
+ // a merged section. If this is the case, issue an error
+ // and also free the merge symbol value.
+ if (!symval.has_output_value())
+ {
+ const std::string& section_name =
+ arm_object->section_name(shndx);
+ arm_object->error(_("cannot handle branch to local %u "
+ "in a merged section %s"),
+ r_sym, section_name.c_str());
+ }
+ psymval = &symval;
+ }
else
- {
- symval.set_output_value(0);
- }
- symval.set_no_output_symtab_entry();
- psymval = &symval;
+ {
+ // We cannot determine the final value.
+ continue;
+ }
}
}
else
{
- const Symbol* gsym = arm_object->global_symbol(r_sym);
+ const Symbol* gsym;
+ gsym = arm_object->global_symbol(r_sym);
gold_assert(gsym != NULL);
if (gsym->is_forwarder())
gsym = relinfo->symtab->resolve_forwards(gsym);
sym = static_cast<const Sized_symbol<32>*>(gsym);
- if (sym->has_symtab_index())
+ if (sym->has_symtab_index() && sym->symtab_index() != -1U)
symval.set_output_symtab_index(sym->symtab_index());
else
symval.set_no_output_symtab_entry();
// Skip this if the symbol has not output section.
if (status == Symbol_table::CFVS_NO_OUTPUT_SECTION)
continue;
-
symval.set_output_value(value);
+
+ if (gsym->type() == elfcpp::STT_TLS)
+ symval.set_is_tls_symbol();
+ else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
+ symval.set_is_ifunc_symbol();
psymval = &symval;
+
+ is_defined_in_discarded_section =
+ (gsym->is_defined_in_discarded_section()
+ && gsym->is_undefined());
+ shndx = 0;
+ }
+
+ Symbol_value<32> symval2;
+ if (is_defined_in_discarded_section)
+ {
+ if (comdat_behavior == CB_UNDETERMINED)
+ {
+ std::string name = arm_object->section_name(relinfo->data_shndx);
+ comdat_behavior = get_comdat_behavior(name.c_str());
+ }
+ if (comdat_behavior == CB_PRETEND)
+ {
+ // FIXME: This case does not work for global symbols.
+ // We have no place to store the original section index.
+ // Fortunately this does not matter for comdat sections,
+ // only for sections explicitly discarded by a linker
+ // script.
+ bool found;
+ typename elfcpp::Elf_types<32>::Elf_Addr value =
+ arm_object->map_to_kept_section(shndx, &found);
+ if (found)
+ symval2.set_output_value(value + psymval->input_value());
+ else
+ symval2.set_output_value(0);
+ }
+ else
+ {
+ if (comdat_behavior == CB_WARNING)
+ gold_warning_at_location(relinfo, i, offset,
+ _("relocation refers to discarded "
+ "section"));
+ symval2.set_output_value(0);
+ }
+ symval2.set_no_output_symtab_entry();
+ psymval = &symval2;
}
// If symbol is a section symbol, we don't know the actual type of
if (!exidx_input_section->has_errors())
{
unsigned int text_shndx = exidx_input_section->link();
- Output_section *os = arm_relobj->output_section(text_shndx);
+ Output_section* os = arm_relobj->output_section(text_shndx);
if (os != NULL && (os->flags() & elfcpp::SHF_ALLOC) != 0)
sorted_output_sections.insert(os);
}