2010-05-26 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_scan_relocatable_relocs): New class. (Target_arm::relocate_special_relocatable): New method. (Arm_relocate_functions::arm_branch_common): Handle relocatable link. (Arm_relocate_functions::thumb_branch_common): Same. (Target_arm::scan_relocatable_relocs): Use Arm_scan_relocatable_relocs instead of Default_scan_relocatable_relocs. * target-reloc.h (relocate_for_relocatable): Let target handle relocation strategy Relocatable_relocs::RELOC_SPECIAL. * target.h (Sized_target::relocate_special_relocatable): New method.
This commit is contained in:
parent
bca1c3ae45
commit
5c3885291f
@ -1,3 +1,15 @@
|
||||
2010-05-26 Doug Kwan <dougkwan@google.com>
|
||||
|
||||
* arm.cc (Arm_scan_relocatable_relocs): New class.
|
||||
(Target_arm::relocate_special_relocatable): New method.
|
||||
(Arm_relocate_functions::arm_branch_common): Handle relocatable link.
|
||||
(Arm_relocate_functions::thumb_branch_common): Same.
|
||||
(Target_arm::scan_relocatable_relocs): Use Arm_scan_relocatable_relocs
|
||||
instead of Default_scan_relocatable_relocs.
|
||||
* target-reloc.h (relocate_for_relocatable): Let target handle
|
||||
relocation strategy Relocatable_relocs::RELOC_SPECIAL.
|
||||
* target.h (Sized_target::relocate_special_relocatable): New method.
|
||||
|
||||
2010-05-25 Viktor Kutuzov <vkutuzov@accesssoftek.com>
|
||||
|
||||
* timer.cc: Only #include <sys/times.h> if HAVE_TIMES is defined.
|
||||
|
389
gold/arm.cc
389
gold/arm.cc
@ -1956,6 +1956,79 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
|
||||
std::vector<Static_reloc> static_relocs_;
|
||||
};
|
||||
|
||||
// The ARM target has many relocation types with odd-sizes or incontigious
|
||||
// bits. The default handling of relocatable relocation cannot process these
|
||||
// relocations. So we have to extend the default code.
|
||||
|
||||
template<bool big_endian, int sh_type, typename Classify_reloc>
|
||||
class Arm_scan_relocatable_relocs :
|
||||
public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
|
||||
{
|
||||
public:
|
||||
// Return the strategy to use for a local symbol which is a section
|
||||
// symbol, given the relocation type.
|
||||
inline Relocatable_relocs::Reloc_strategy
|
||||
local_section_strategy(unsigned int r_type, Relobj*)
|
||||
{
|
||||
if (sh_type == elfcpp::SHT_RELA)
|
||||
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
|
||||
else
|
||||
{
|
||||
if (r_type == elfcpp::R_ARM_TARGET1
|
||||
|| r_type == elfcpp::R_ARM_TARGET2)
|
||||
{
|
||||
const Target_arm<big_endian>* arm_target =
|
||||
Target_arm<big_endian>::default_target();
|
||||
r_type = arm_target->get_real_reloc_type(r_type);
|
||||
}
|
||||
|
||||
switch(r_type)
|
||||
{
|
||||
// Relocations that write nothing. These exclude R_ARM_TARGET1
|
||||
// and R_ARM_TARGET2.
|
||||
case elfcpp::R_ARM_NONE:
|
||||
case elfcpp::R_ARM_V4BX:
|
||||
case elfcpp::R_ARM_TLS_GOTDESC:
|
||||
case elfcpp::R_ARM_TLS_CALL:
|
||||
case elfcpp::R_ARM_TLS_DESCSEQ:
|
||||
case elfcpp::R_ARM_THM_TLS_CALL:
|
||||
case elfcpp::R_ARM_GOTRELAX:
|
||||
case elfcpp::R_ARM_GNU_VTENTRY:
|
||||
case elfcpp::R_ARM_GNU_VTINHERIT:
|
||||
case elfcpp::R_ARM_THM_TLS_DESCSEQ16:
|
||||
case elfcpp::R_ARM_THM_TLS_DESCSEQ32:
|
||||
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
|
||||
// These should have been converted to something else above.
|
||||
case elfcpp::R_ARM_TARGET1:
|
||||
case elfcpp::R_ARM_TARGET2:
|
||||
gold_unreachable();
|
||||
// Relocations that write full 32 bits.
|
||||
case elfcpp::R_ARM_ABS32:
|
||||
case elfcpp::R_ARM_REL32:
|
||||
case elfcpp::R_ARM_SBREL32:
|
||||
case elfcpp::R_ARM_GOTOFF32:
|
||||
case elfcpp::R_ARM_BASE_PREL:
|
||||
case elfcpp::R_ARM_GOT_BREL:
|
||||
case elfcpp::R_ARM_BASE_ABS:
|
||||
case elfcpp::R_ARM_ABS32_NOI:
|
||||
case elfcpp::R_ARM_REL32_NOI:
|
||||
case elfcpp::R_ARM_PLT32_ABS:
|
||||
case elfcpp::R_ARM_GOT_ABS:
|
||||
case elfcpp::R_ARM_GOT_PREL:
|
||||
case elfcpp::R_ARM_TLS_GD32:
|
||||
case elfcpp::R_ARM_TLS_LDM32:
|
||||
case elfcpp::R_ARM_TLS_LDO32:
|
||||
case elfcpp::R_ARM_TLS_IE32:
|
||||
case elfcpp::R_ARM_TLS_LE32:
|
||||
return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4;
|
||||
default:
|
||||
// For all other static relocations, return RELOC_SPECIAL.
|
||||
return Relocatable_relocs::RELOC_SPECIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Utilities for manipulating integers of up to 32-bits
|
||||
|
||||
namespace utils
|
||||
@ -2189,6 +2262,21 @@ class Target_arm : public Sized_target<32, big_endian>
|
||||
unsigned char* reloc_view,
|
||||
section_size_type reloc_view_size);
|
||||
|
||||
// Perform target-specific processing in a relocatable link. This is
|
||||
// only used if we use the relocation strategy RELOC_SPECIAL.
|
||||
void
|
||||
relocate_special_relocatable(const Relocate_info<32, big_endian>* relinfo,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* preloc_in,
|
||||
size_t relnum,
|
||||
Output_section* output_section,
|
||||
off_t offset_in_output_section,
|
||||
unsigned char* view,
|
||||
typename elfcpp::Elf_types<32>::Elf_Addr
|
||||
view_address,
|
||||
section_size_type view_size,
|
||||
unsigned char* preloc_out);
|
||||
|
||||
// Return whether SYM is defined by the ABI.
|
||||
bool
|
||||
do_is_defined_by_abi(Symbol* sym) const
|
||||
@ -3725,6 +3813,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
|
||||
Target_arm<big_endian>::default_target();
|
||||
if (is_weakly_undefined_without_plt)
|
||||
{
|
||||
gold_assert(!parameters->options().relocatable());
|
||||
Valtype cond = val & 0xf0000000U;
|
||||
if (arm_target->may_use_arm_nop())
|
||||
val = cond | 0x0320f000;
|
||||
@ -3742,8 +3831,11 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
|
||||
// to switch mode.
|
||||
bool may_use_blx = arm_target->may_use_blx();
|
||||
Reloc_stub* stub = NULL;
|
||||
if (utils::has_overflow<26>(branch_offset)
|
||||
|| ((thumb_bit != 0) && !(may_use_blx && r_type == elfcpp::R_ARM_CALL)))
|
||||
|
||||
if (!parameters->options().relocatable()
|
||||
&& (utils::has_overflow<26>(branch_offset)
|
||||
|| ((thumb_bit != 0)
|
||||
&& !(may_use_blx && r_type == elfcpp::R_ARM_CALL))))
|
||||
{
|
||||
Valtype unadjusted_branch_target = psymval->value(object, 0);
|
||||
|
||||
@ -3850,6 +3942,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
|
||||
Target_arm<big_endian>::default_target();
|
||||
if (is_weakly_undefined_without_plt)
|
||||
{
|
||||
gold_assert(!parameters->options().relocatable());
|
||||
if (arm_target->may_use_thumb2_nop())
|
||||
{
|
||||
elfcpp::Swap<16, big_endian>::writeval(wv, 0xf3af);
|
||||
@ -3876,11 +3969,12 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
|
||||
// We need a stub if the branch offset is too large or if we need
|
||||
// to switch mode.
|
||||
bool thumb2 = arm_target->using_thumb2();
|
||||
if ((!thumb2 && utils::has_overflow<23>(branch_offset))
|
||||
if (!parameters->options().relocatable()
|
||||
&& ((!thumb2 && utils::has_overflow<23>(branch_offset))
|
||||
|| (thumb2 && utils::has_overflow<25>(branch_offset))
|
||||
|| ((thumb_bit == 0)
|
||||
&& (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx)
|
||||
|| r_type == elfcpp::R_ARM_THM_JUMP24)))
|
||||
|| r_type == elfcpp::R_ARM_THM_JUMP24))))
|
||||
{
|
||||
Arm_address unadjusted_branch_target = psymval->value(object, 0);
|
||||
|
||||
@ -8919,7 +9013,7 @@ Target_arm<big_endian>::scan_relocatable_relocs(
|
||||
{
|
||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||
|
||||
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
|
||||
typedef Arm_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
|
||||
Relocatable_size_for_reloc> Scan_relocatable_relocs;
|
||||
|
||||
gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL,
|
||||
@ -8971,6 +9065,291 @@ Target_arm<big_endian>::relocate_for_relocatable(
|
||||
reloc_view_size);
|
||||
}
|
||||
|
||||
// Perform target-specific processing in a relocatable link. This is
|
||||
// only used if we use the relocation strategy RELOC_SPECIAL.
|
||||
|
||||
template<bool big_endian>
|
||||
void
|
||||
Target_arm<big_endian>::relocate_special_relocatable(
|
||||
const Relocate_info<32, big_endian>* relinfo,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* preloc_in,
|
||||
size_t relnum,
|
||||
Output_section* output_section,
|
||||
off_t offset_in_output_section,
|
||||
unsigned char* view,
|
||||
elfcpp::Elf_types<32>::Elf_Addr view_address,
|
||||
section_size_type,
|
||||
unsigned char* preloc_out)
|
||||
{
|
||||
// We can only handle REL type relocation sections.
|
||||
gold_assert(sh_type == elfcpp::SHT_REL);
|
||||
|
||||
typedef typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc Reltype;
|
||||
typedef typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc_write
|
||||
Reltype_write;
|
||||
const Arm_address invalid_address = static_cast<Arm_address>(0) - 1;
|
||||
|
||||
const Arm_relobj<big_endian>* object =
|
||||
Arm_relobj<big_endian>::as_arm_relobj(relinfo->object);
|
||||
const unsigned int local_count = object->local_symbol_count();
|
||||
|
||||
Reltype reloc(preloc_in);
|
||||
Reltype_write reloc_write(preloc_out);
|
||||
|
||||
elfcpp::Elf_types<32>::Elf_WXword r_info = reloc.get_r_info();
|
||||
const unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
|
||||
const unsigned int r_type = elfcpp::elf_r_type<32>(r_info);
|
||||
|
||||
const Arm_reloc_property* arp =
|
||||
arm_reloc_property_table->get_implemented_static_reloc_property(r_type);
|
||||
gold_assert(arp != NULL);
|
||||
|
||||
// Get the new symbol index.
|
||||
// We only use RELOC_SPECIAL strategy in local relocations.
|
||||
gold_assert(r_sym < local_count);
|
||||
|
||||
// We are adjusting a section symbol. We need to find
|
||||
// the symbol table index of the section symbol for
|
||||
// the output section corresponding to input section
|
||||
// in which this symbol is defined.
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = object->local_symbol_input_shndx(r_sym, &is_ordinary);
|
||||
gold_assert(is_ordinary);
|
||||
Output_section* os = object->output_section(shndx);
|
||||
gold_assert(os != NULL);
|
||||
gold_assert(os->needs_symtab_index());
|
||||
unsigned int new_symndx = os->symtab_index();
|
||||
|
||||
// Get the new offset--the location in the output section where
|
||||
// this relocation should be applied.
|
||||
|
||||
Arm_address offset = reloc.get_r_offset();
|
||||
Arm_address new_offset;
|
||||
if (offset_in_output_section != invalid_address)
|
||||
new_offset = offset + offset_in_output_section;
|
||||
else
|
||||
{
|
||||
section_offset_type sot_offset =
|
||||
convert_types<section_offset_type, Arm_address>(offset);
|
||||
section_offset_type new_sot_offset =
|
||||
output_section->output_offset(object, relinfo->data_shndx,
|
||||
sot_offset);
|
||||
gold_assert(new_sot_offset != -1);
|
||||
new_offset = new_sot_offset;
|
||||
}
|
||||
|
||||
// In an object file, r_offset is an offset within the section.
|
||||
// In an executable or dynamic object, generated by
|
||||
// --emit-relocs, r_offset is an absolute address.
|
||||
if (!parameters->options().relocatable())
|
||||
{
|
||||
new_offset += view_address;
|
||||
if (offset_in_output_section != invalid_address)
|
||||
new_offset -= offset_in_output_section;
|
||||
}
|
||||
|
||||
reloc_write.put_r_offset(new_offset);
|
||||
reloc_write.put_r_info(elfcpp::elf_r_info<32>(new_symndx, r_type));
|
||||
|
||||
// Handle the reloc addend.
|
||||
// The relocation uses a section symbol in the input file.
|
||||
// We are adjusting it to use a section symbol in the output
|
||||
// file. The input section symbol refers to some address in
|
||||
// the input section. We need the relocation in the output
|
||||
// file to refer to that same address. This adjustment to
|
||||
// the addend is the same calculation we use for a simple
|
||||
// absolute relocation for the input section symbol.
|
||||
|
||||
const Symbol_value<32>* psymval = object->local_symbol(r_sym);
|
||||
|
||||
// Handle THUMB bit.
|
||||
Symbol_value<32> symval;
|
||||
Arm_address thumb_bit =
|
||||
object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
|
||||
if (thumb_bit != 0
|
||||
&& arp->uses_thumb_bit()
|
||||
&& ((psymval->value(object, 0) & 1) != 0))
|
||||
{
|
||||
Arm_address stripped_value =
|
||||
psymval->value(object, 0) & ~static_cast<Arm_address>(1);
|
||||
symval.set_output_value(stripped_value);
|
||||
psymval = &symval;
|
||||
}
|
||||
|
||||
unsigned char* paddend = view + offset;
|
||||
typename Arm_relocate_functions<big_endian>::Status reloc_status =
|
||||
Arm_relocate_functions<big_endian>::STATUS_OKAY;
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_ARM_ABS8:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::abs8(paddend, object,
|
||||
psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS12:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::abs12(paddend, object,
|
||||
psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_ABS16:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::abs16(paddend, object,
|
||||
psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_ABS5:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::thm_abs5(paddend,
|
||||
object,
|
||||
psymval);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_MOVW_ABS_NC:
|
||||
case elfcpp::R_ARM_MOVW_PREL_NC:
|
||||
case elfcpp::R_ARM_MOVW_BREL_NC:
|
||||
case elfcpp::R_ARM_MOVW_BREL:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::movw(
|
||||
paddend, object, psymval, 0, thumb_bit, arp->checks_overflow());
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
|
||||
case elfcpp::R_ARM_THM_MOVW_PREL_NC:
|
||||
case elfcpp::R_ARM_THM_MOVW_BREL_NC:
|
||||
case elfcpp::R_ARM_THM_MOVW_BREL:
|
||||
reloc_status = Arm_relocate_functions<big_endian>::thm_movw(
|
||||
paddend, object, psymval, 0, thumb_bit, arp->checks_overflow());
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_CALL:
|
||||
case elfcpp::R_ARM_THM_XPC22:
|
||||
case elfcpp::R_ARM_THM_JUMP24:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thumb_branch_common(
|
||||
r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
|
||||
false);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_PLT32:
|
||||
case elfcpp::R_ARM_CALL:
|
||||
case elfcpp::R_ARM_JUMP24:
|
||||
case elfcpp::R_ARM_XPC25:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::arm_branch_common(
|
||||
r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
|
||||
false);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_JUMP19:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_jump19(paddend, object,
|
||||
psymval, 0, thumb_bit);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_JUMP6:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_jump6(paddend, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_JUMP8:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_jump8(paddend, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_JUMP11:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_jump11(paddend, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_PREL31:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::prel31(paddend, object, psymval, 0,
|
||||
thumb_bit);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_PC8:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_pc8(paddend, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_PC12:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_pc12(paddend, object, psymval,
|
||||
0);
|
||||
break;
|
||||
|
||||
case elfcpp::R_ARM_THM_ALU_PREL_11_0:
|
||||
reloc_status =
|
||||
Arm_relocate_functions<big_endian>::thm_alu11(paddend, object, psymval,
|
||||
0, thumb_bit);
|
||||
break;
|
||||
|
||||
// These relocation truncate relocation results so we cannot handle them
|
||||
// in a relocatable link.
|
||||
case elfcpp::R_ARM_MOVT_ABS:
|
||||
case elfcpp::R_ARM_THM_MOVT_ABS:
|
||||
case elfcpp::R_ARM_MOVT_PREL:
|
||||
case elfcpp::R_ARM_MOVT_BREL:
|
||||
case elfcpp::R_ARM_THM_MOVT_PREL:
|
||||
case elfcpp::R_ARM_THM_MOVT_BREL:
|
||||
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_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_PC_G0:
|
||||
case elfcpp::R_ARM_LDR_PC_G1:
|
||||
case elfcpp::R_ARM_LDR_PC_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_PC_G0:
|
||||
case elfcpp::R_ARM_LDRS_PC_G1:
|
||||
case elfcpp::R_ARM_LDRS_PC_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_PC_G0:
|
||||
case elfcpp::R_ARM_LDC_PC_G1:
|
||||
case elfcpp::R_ARM_LDC_PC_G2:
|
||||
case elfcpp::R_ARM_LDC_SB_G0:
|
||||
case elfcpp::R_ARM_LDC_SB_G1:
|
||||
case elfcpp::R_ARM_LDC_SB_G2:
|
||||
gold_error(_("cannot handle %s in a relocatable link"),
|
||||
arp->name().c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Report any errors.
|
||||
switch (reloc_status)
|
||||
{
|
||||
case Arm_relocate_functions<big_endian>::STATUS_OKAY:
|
||||
break;
|
||||
case Arm_relocate_functions<big_endian>::STATUS_OVERFLOW:
|
||||
gold_error_at_location(relinfo, relnum, reloc.get_r_offset(),
|
||||
_("relocation overflow in %s"),
|
||||
arp->name().c_str());
|
||||
break;
|
||||
case Arm_relocate_functions<big_endian>::STATUS_BAD_RELOC:
|
||||
gold_error_at_location(relinfo, relnum, reloc.get_r_offset(),
|
||||
_("unexpected opcode while processing relocation %s"),
|
||||
arp->name().c_str());
|
||||
break;
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
// Return the value to use for a dynamic symbol which requires special
|
||||
// treatment. This is how we support equality comparisons of function
|
||||
// pointers across shared library boundaries, as described in the
|
||||
|
@ -515,7 +515,7 @@ relocate_for_relocatable(
|
||||
const Relocatable_relocs* rr,
|
||||
unsigned char* view,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
|
||||
section_size_type,
|
||||
section_size_type view_size,
|
||||
unsigned char* reloc_view,
|
||||
section_size_type reloc_view_size)
|
||||
{
|
||||
@ -537,6 +537,19 @@ relocate_for_relocatable(
|
||||
if (strategy == Relocatable_relocs::RELOC_DISCARD)
|
||||
continue;
|
||||
|
||||
if (strategy == Relocatable_relocs::RELOC_SPECIAL)
|
||||
{
|
||||
// Target wants to handle this relocation.
|
||||
Sized_target<size, big_endian>* target =
|
||||
parameters->sized_target<size, big_endian>();
|
||||
target->relocate_special_relocatable(relinfo, sh_type, prelocs,
|
||||
i, output_section,
|
||||
offset_in_output_section,
|
||||
view, view_address,
|
||||
view_size, pwrite);
|
||||
pwrite += reloc_size;
|
||||
continue;
|
||||
}
|
||||
Reltype reloc(prelocs);
|
||||
Reltype_write reloc_write(pwrite);
|
||||
|
||||
|
@ -688,6 +688,36 @@ class Sized_target : public Target
|
||||
unsigned char* reloc_view,
|
||||
section_size_type reloc_view_size) = 0;
|
||||
|
||||
// Perform target-specific processing in a relocatable link. This is
|
||||
// only used if we use the relocation strategy RELOC_SPECIAL.
|
||||
// RELINFO points to a Relocation_info structure. SH_TYPE is the relocation
|
||||
// section type. PRELOC_IN points to the original relocation. RELNUM is
|
||||
// the index number of the relocation in the relocation section.
|
||||
// OUTPUT_SECTION is the output section to which the relocation is applied.
|
||||
// OFFSET_IN_OUTPUT_SECTION is the offset of the relocation input section
|
||||
// within the output section. VIEW points to the output view of the
|
||||
// output section. VIEW_ADDRESS is output address of the view. VIEW_SIZE
|
||||
// is the size of the output view and PRELOC_OUT points to the new
|
||||
// relocation in the output object.
|
||||
//
|
||||
// A target only needs to override this if the generic code in
|
||||
// target-reloc.h cannot handle some relocation types.
|
||||
|
||||
virtual void
|
||||
relocate_special_relocatable(const Relocate_info<size, big_endian>*
|
||||
/*relinfo */,
|
||||
unsigned int /* sh_type */,
|
||||
const unsigned char* /* preloc_in */,
|
||||
size_t /* relnum */,
|
||||
Output_section* /* output_section */,
|
||||
off_t /* offset_in_output_section */,
|
||||
unsigned char* /* view */,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr
|
||||
/* view_address */,
|
||||
section_size_type /* view_size */,
|
||||
unsigned char* /* preloc_out*/)
|
||||
{ gold_unreachable(); }
|
||||
|
||||
protected:
|
||||
Sized_target(const Target::Target_info* pti)
|
||||
: Target(pti)
|
||||
|
Loading…
x
Reference in New Issue
Block a user