// Ideally we would like to avoid using global variables but this is used
// very in many places and sometimes in loops. If we use a function
-// returning a static instance of Arm_reloc_property_table, it will very
+// returning a static instance of Arm_reloc_property_table, it will be very
// slow in an threaded environment since the static instance needs to be
// locked. The pointer is below initialized in the
// Target::do_select_as_default_target() hook so that we do not spend time
// If this is a local symbol, this is the index in the defining object.
// Otherwise, it is invalid_index for a global symbol.
unsigned int r_sym_;
- // If r_sym_ is invalid index. This points to a global symbol.
- // Otherwise, this points a relobj. We used the unsized and target
+ // If r_sym_ is an invalid index, this points to a global symbol.
+ // Otherwise, it points to a relobj. We used the unsized and target
// independent Symbol and Relobj classes instead of Sized_symbol<32> and
- // Arm_relobj. This is done to avoid making the stub class a template
+ // Arm_relobj, in order to avoid making the stub class a template
// as most of the stub machinery is endianness-neutral. However, it
// may require a bit of casting done by users of this class.
union
current_data_size() const
{ return this->current_data_size_for_child(); }
- // Add a STUB with using KEY. Caller is reponsible for avoid adding
- // if already a STUB with the same key has been added.
+ // Add a STUB using KEY. The caller is responsible for avoiding addition
+ // if a STUB with the same key has already been added.
void
add_reloc_stub(Reloc_stub* stub, const Reloc_stub::Key& key)
{
}
// Add a Cortex-A8 STUB that fixes up a THUMB branch at ADDRESS.
- // Caller is reponsible for avoid adding if already a STUB with the same
- // address has been added.
+ // The caller is responsible for avoiding addition if a STUB with the same
+ // address has already been added.
void
add_cortex_a8_stub(Arm_address address, Cortex_a8_stub* stub)
{
// number of bytes to be deleted in output. If parts of the input EXIDX
// section are merged a heap allocated Arm_exidx_section_offset_map is store
// in the located PSECTION_OFFSET_MAP. The caller owns the map and is
- // reponsible for releasing it.
+ // responsible for releasing it.
template<bool big_endian>
uint32_t
process_exidx_section(const Arm_exidx_input_section* exidx_input_section,
Target_arm<big_endian>*);
// Find the linked text section of an EXIDX section by looking at the
- // first reloction of the EXIDX section. PSHDR points to the section
+ // first relocation of the EXIDX section. PSHDR points to the section
// headers of a relocation section and PSYMS points to the local symbols.
// PSHNDX points to a location storing the text section index if found.
// Return whether we can find the linked section.
std::vector<Static_reloc> static_relocs_;
};
-// The ARM target has many relocation types with odd-sizes or incontigious
+// The ARM target has many relocation types with odd-sizes or noncontiguous
// bits. The default handling of relocatable relocation cannot process these
// relocations. So we have to extend the default code.
: issued_non_pic_error_(false)
{ }
+ static inline int
+ get_reference_flags(unsigned int r_type);
+
inline void
local(Symbol_table* symtab, Layout* layout, Target_arm* target,
Sized_relobj<32, big_endian>* object,
// Return whether the static relocation needs to be applied.
inline bool
should_apply_static_reloc(const Sized_symbol<32>* gsym,
- int ref_flags,
+ unsigned int r_type,
bool is_32bit,
Output_section* output_section);
typedef enum
{
STATUS_OKAY, // No error during relocation.
- STATUS_OVERFLOW, // Relocation oveflow.
+ STATUS_OVERFLOW, // Relocation overflow.
STATUS_BAD_RELOC // Relocation cannot be applied.
} Status;
// Insert OFFSET to a 32-bit THUMB conditional branch and return the lower
// instruction. LOWER_INSN is the original lower instruction of the branch.
- // Caller is reponsible for overflow checking.
+ // The caller is responsible for overflow checking.
static inline uint16_t
thumb32_cond_branch_lower(uint16_t lower_insn, int32_t offset)
{
// Determine the type of stub needed, if any, for a relocation of R_TYPE at
// LOCATION to DESTINATION.
// This code is based on the arm_type_of_stub function in
-// bfd/elf32-arm.c. We have changed the interface a liitle to keep the Stub
+// bfd/elf32-arm.c. We have changed the interface a little to keep the Stub
// class simple.
Stub_type
// Stub_table methods.
-// Removel all Cortex-A8 stub.
+// Remove all Cortex-A8 stub.
template<bool big_endian>
void
// dropping. If there is no entry (x0, y0) for an input offset x0,
// the output offset y0 of it is determined by the output offset y1 of
// the smallest input offset x1 > x0 that there is an (x1, y1) entry
- // in the map. If y1 is not -1, then y0 = y1 + x0 - x1. Othewise, y1
+ // in the map. If y1 is not -1, then y0 = y1 + x0 - x1. Otherwise, y1
// y0 is also -1.
if (delete_entry != prev_delete_entry && i != 0)
this->update_offset_map(i - 1, deleted_bytes, prev_delete_entry);
section_size_type section_end_offset =
section_begin_offset + p->data_size();
- // Check to see if we should group the previously seens sections.
+ // Check to see if we should group the previously seen sections.
switch (state)
{
case NO_GROUP:
// harder because we cannot access this information. So we override the
// do_count_local_symbol in parent and scan local symbols to mark
// THUMB functions. This is not the most efficient way but I do not want to
-// slow down other ports by calling a per symbol targer hook inside
+// slow down other ports by calling a per symbol target hook inside
// Sized_relobj<size, big_endian>::do_count_local_symbols.
template<bool big_endian>
if (loccount == 0)
return;
- // Intialize the thumb function bit-vector.
+ // Initialize the thumb function bit-vector.
std::vector<bool> empty_vector(loccount, false);
this->local_symbol_is_thumb_function_.swap(empty_vector);
}
}
-// Find the linked text section of an EXIDX section by looking the the first
+// Find the linked text section of an EXIDX section by looking at the first
// relocation. 4.4.1 of the EHABI specifications says that an EXIDX section
-// must be linked to to its associated code section via the sh_link field of
+// must be linked to its associated code section via the sh_link field of
// its section header. However, some tools are broken and the link is not
// always set. LD just drops such an EXIDX section silently, causing the
// associated code not unwindabled. Here we try a little bit harder to
exidx_input_section->set_has_errors();
}
else if ((text_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) == 0)
- // I would like to make this an error but currenlty ld just ignores
+ // I would like to make this an error but currently ld just ignores
// this.
gold_warning(_("EXIDX section %s(%u) links to non-executable section "
"%s(%u) in %s"),
// Process relocations for garbage collection. The ARM target uses .ARM.exidx
// sections for unwinding. These sections are referenced implicitly by
-// text sections linked in the section headers. If we ignore these implict
+// text sections linked in the section headers. If we ignore these implicit
// references, the .ARM.exidx sections and any .ARM.extab sections they use
// will be garbage-collected incorrectly. Hence we override the same function
// in the base class to handle these implicit references.
return tls::TLSOPT_NONE;
}
+// Get the Reference_flags for a particular relocation.
+
+template<bool big_endian>
+int
+Target_arm<big_endian>::Scan::get_reference_flags(unsigned int r_type)
+{
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_NONE:
+ case elfcpp::R_ARM_V4BX:
+ case elfcpp::R_ARM_GNU_VTENTRY:
+ case elfcpp::R_ARM_GNU_VTINHERIT:
+ // No symbol reference.
+ return 0;
+
+ case elfcpp::R_ARM_ABS32:
+ case elfcpp::R_ARM_ABS16:
+ case elfcpp::R_ARM_ABS12:
+ case elfcpp::R_ARM_THM_ABS5:
+ case elfcpp::R_ARM_ABS8:
+ case elfcpp::R_ARM_BASE_ABS:
+ case elfcpp::R_ARM_MOVW_ABS_NC:
+ case elfcpp::R_ARM_MOVT_ABS:
+ case elfcpp::R_ARM_THM_MOVW_ABS_NC:
+ case elfcpp::R_ARM_THM_MOVT_ABS:
+ case elfcpp::R_ARM_ABS32_NOI:
+ return Symbol::ABSOLUTE_REF;
+
+ case elfcpp::R_ARM_REL32:
+ case elfcpp::R_ARM_LDR_PC_G0:
+ case elfcpp::R_ARM_SBREL32:
+ case elfcpp::R_ARM_THM_PC8:
+ case elfcpp::R_ARM_BASE_PREL:
+ case elfcpp::R_ARM_MOVW_PREL_NC:
+ case elfcpp::R_ARM_MOVT_PREL:
+ case elfcpp::R_ARM_THM_MOVW_PREL_NC:
+ case elfcpp::R_ARM_THM_MOVT_PREL:
+ case elfcpp::R_ARM_THM_ALU_PREL_11_0:
+ case elfcpp::R_ARM_THM_PC12:
+ case elfcpp::R_ARM_REL32_NOI:
+ case elfcpp::R_ARM_ALU_PC_G0_NC:
+ case elfcpp::R_ARM_ALU_PC_G0:
+ case elfcpp::R_ARM_ALU_PC_G1_NC:
+ case elfcpp::R_ARM_ALU_PC_G1:
+ case elfcpp::R_ARM_ALU_PC_G2:
+ case elfcpp::R_ARM_LDR_PC_G1:
+ case elfcpp::R_ARM_LDR_PC_G2:
+ case elfcpp::R_ARM_LDRS_PC_G0:
+ case elfcpp::R_ARM_LDRS_PC_G1:
+ case elfcpp::R_ARM_LDRS_PC_G2:
+ case elfcpp::R_ARM_LDC_PC_G0:
+ case elfcpp::R_ARM_LDC_PC_G1:
+ case elfcpp::R_ARM_LDC_PC_G2:
+ case elfcpp::R_ARM_ALU_SB_G0_NC:
+ case elfcpp::R_ARM_ALU_SB_G0:
+ case elfcpp::R_ARM_ALU_SB_G1_NC:
+ case elfcpp::R_ARM_ALU_SB_G1:
+ case elfcpp::R_ARM_ALU_SB_G2:
+ case elfcpp::R_ARM_LDR_SB_G0:
+ case elfcpp::R_ARM_LDR_SB_G1:
+ case elfcpp::R_ARM_LDR_SB_G2:
+ case elfcpp::R_ARM_LDRS_SB_G0:
+ case elfcpp::R_ARM_LDRS_SB_G1:
+ case elfcpp::R_ARM_LDRS_SB_G2:
+ case elfcpp::R_ARM_LDC_SB_G0:
+ case elfcpp::R_ARM_LDC_SB_G1:
+ case elfcpp::R_ARM_LDC_SB_G2:
+ case elfcpp::R_ARM_MOVW_BREL_NC:
+ case elfcpp::R_ARM_MOVT_BREL:
+ case elfcpp::R_ARM_MOVW_BREL:
+ case elfcpp::R_ARM_THM_MOVW_BREL_NC:
+ case elfcpp::R_ARM_THM_MOVT_BREL:
+ case elfcpp::R_ARM_THM_MOVW_BREL:
+ case elfcpp::R_ARM_GOTOFF32:
+ case elfcpp::R_ARM_GOTOFF12:
+ case elfcpp::R_ARM_SBREL31:
+ return Symbol::RELATIVE_REF;
+
+ case elfcpp::R_ARM_PLT32:
+ case elfcpp::R_ARM_CALL:
+ case elfcpp::R_ARM_JUMP24:
+ case elfcpp::R_ARM_THM_CALL:
+ case elfcpp::R_ARM_THM_JUMP24:
+ case elfcpp::R_ARM_THM_JUMP19:
+ case elfcpp::R_ARM_THM_JUMP6:
+ case elfcpp::R_ARM_THM_JUMP11:
+ case elfcpp::R_ARM_THM_JUMP8:
+ // R_ARM_PREL31 is not used to relocate call/jump instructions but
+ // in unwind tables. It may point to functions via PLTs.
+ // So we treat it like call/jump relocations above.
+ case elfcpp::R_ARM_PREL31:
+ return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+
+ case elfcpp::R_ARM_GOT_BREL:
+ case elfcpp::R_ARM_GOT_ABS:
+ case elfcpp::R_ARM_GOT_PREL:
+ // Absolute in GOT.
+ return Symbol::ABSOLUTE_REF;
+
+ case elfcpp::R_ARM_TLS_GD32: // Global-dynamic
+ case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic
+ case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic
+ case elfcpp::R_ARM_TLS_IE32: // Initial-exec
+ case elfcpp::R_ARM_TLS_LE32: // Local-exec
+ return Symbol::TLS_REF;
+
+ case elfcpp::R_ARM_TARGET1:
+ case elfcpp::R_ARM_TARGET2:
+ case elfcpp::R_ARM_COPY:
+ case elfcpp::R_ARM_GLOB_DAT:
+ case elfcpp::R_ARM_JUMP_SLOT:
+ case elfcpp::R_ARM_RELATIVE:
+ case elfcpp::R_ARM_PC24:
+ case elfcpp::R_ARM_LDR_SBREL_11_0_NC:
+ case elfcpp::R_ARM_ALU_SBREL_19_12_NC:
+ case elfcpp::R_ARM_ALU_SBREL_27_20_CK:
+ default:
+ // Not expected. We will give an error later.
+ return 0;
+ }
+}
+
// Report an unsupported relocation against a local symbol.
template<bool big_endian>
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (gsym->may_need_copy_reloc())
{
// Relative addressing relocations.
{
// Make a dynamic relocation if necessary.
- int flags = Symbol::NON_PIC_REF;
- if (gsym->needs_dynamic_reloc(flags))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (target->may_need_copy_reloc(gsym))
{
// All the relocation above are branches except for the PREL31 ones.
// A PREL31 relocation can point to a personality function in a shared
// library. In that case we want to use a PLT because we want to
- // call the personality routine and the dyanmic linkers we care about
+ // call the personality routine and the dynamic linkers we care about
// do not support dynamic PREL31 relocations. An REL31 relocation may
// point to a function whose unwinding behaviour is being described but
// we will not mistakenly generate a PLT for that because we should use
if (exidx_section != NULL
&& exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
{
- // Create __exidx_start and __exdix_end symbols.
+ // Create __exidx_start and __exidx_end symbols.
symtab->define_in_output_data("__exidx_start", NULL,
Symbol_table::PREDEFINED,
exidx_section, 0, 0, elfcpp::STT_OBJECT,
inline bool
Target_arm<big_endian>::Relocate::should_apply_static_reloc(
const Sized_symbol<32>* gsym,
- int ref_flags,
+ unsigned int r_type,
bool is_32bit,
Output_section* output_section)
{
if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0)
return true;
+ int ref_flags = Scan::get_reference_flags(r_type);
+
// For local symbols, we will have created a non-RELATIVE dynamic
// relocation only if (a) the output is position independent,
// (b) the relocation is absolute (not pc- or segment-relative), and
{
// This is a global symbol. Determine if we use PLT and if the
// final target is THUMB.
- if (gsym->use_plt_offset(reloc_is_non_pic(r_type)))
+ if (gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
// This uses a PLT, change the symbol value.
symval.set_output_value(target->plt_section()->address()
break;
case elfcpp::R_ARM_ABS8:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::abs8(view, object, psymval);
break;
case elfcpp::R_ARM_ABS12:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::abs12(view, object, psymval);
break;
case elfcpp::R_ARM_ABS16:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::abs16(view, object, psymval);
break;
case elfcpp::R_ARM_ABS32:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, true, output_section))
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
thumb_bit);
break;
case elfcpp::R_ARM_ABS32_NOI:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, true, output_section))
// No thumb bit for this relocation: (S + A)
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
0);
break;
case elfcpp::R_ARM_MOVW_ABS_NC:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::movw(view, object, psymval,
0, thumb_bit,
check_overflow);
break;
case elfcpp::R_ARM_MOVT_ABS:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::movt(view, object, psymval, 0);
break;
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::thm_movw(view, object, psymval,
0, thumb_bit, false);
break;
case elfcpp::R_ARM_THM_MOVT_ABS:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::thm_movt(view, object,
psymval, 0);
break;
break;
case elfcpp::R_ARM_THM_ABS5:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::thm_abs5(view, object, psymval);
break;
break;
case elfcpp::R_ARM_BASE_ABS:
- {
- if (!should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
- break;
-
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::base_abs(view, sym_origin);
- }
break;
case elfcpp::R_ARM_GOT_BREL:
return elfcpp::R_ARM_ABS32;
case elfcpp::R_ARM_TARGET2:
- // This can be any reloc type but ususally is R_ARM_GOT_PREL
+ // This can be any reloc type but usually is R_ARM_GOT_PREL
return elfcpp::R_ARM_GOT_PREL;
default:
|| (out_attr[elfcpp::Tag_ABI_align8_preserved].int_value()
== 0)))
{
- // This error message should be enabled once all non-conformant
+ // This error message should be enabled once all non-conforming
// binaries in the toolchain have had the attributes set
// properly.
// gold_error(_("output 8-byte data alignment conflicts with %s"),
}
break;
case elfcpp::Tag_ABI_VFP_args:
- // Aready done.
+ // Already done.
break;
case elfcpp::Tag_ABI_WMMX_args:
if (in_attr[i].int_value() != out_attr[i].int_value()
{
// This is a global symbol. Determine if we use PLT and if the
// final target is THUMB.
- if (gsym->use_plt_offset(Relocate::reloc_is_non_pic(r_type)))
+ if (gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
// This uses a PLT, change the symbol value.
symval.set_output_value(this->plt_section()->address()
// Group input sections for stub generation.
//
-// We goup input sections in an output sections so that the total size,
+// We group input sections in an output section so that the total size,
// including any padding space due to alignment is smaller than GROUP_SIZE
// unless the only input section in group is bigger than GROUP_SIZE already.
// Then an ARM stub table is created to follow the last input section
// in group. For each group an ARM stub table is created an is placed
-// after the last group. If STUB_ALWATS_AFTER_BRANCH is false, we further
+// after the last group. If STUB_ALWAYS_AFTER_BRANCH is false, we further
// extend the group after the stub table.
template<bool big_endian>
{
// Determine the stub group size. The group size is the absolute
// value of the parameter --stub-group-size. If --stub-group-size
- // is passed a negative value, we restict stubs to be always after
+ // is passed a negative value, we restrict stubs to be always after
// the stubbed branches.
int32_t stub_group_size_param =
parameters->options().stub_group_size();
{
// Reorder the known object attributes in output. We want to move
// Tag_conformance to position 4 and Tag_conformance to position 5
- // and shift eveything between 4 .. Tag_conformance - 1 to make room.
+ // and shift everything between 4 .. Tag_conformance - 1 to make room.
if (num == 4)
return elfcpp::Tag_conformance;
if (num == 5)
switch (stub->stub_template()->type())
{
case arm_stub_a8_veneer_b_cond:
- // For a conditional branch, we re-write it to be a uncondition
+ // For a conditional branch, we re-write it to be an unconditional
// branch to the stub. We use the THUMB-2 encoding here.
upper_insn = 0xf000U;
lower_insn = 0xb800U;