[PATCH][GOLD] Handle target specific relocatable relocation.
Doug Kwan (關振德)
dougkwan@google.com
Tue May 25 03:30:00 GMT 2010
Hi,
This patch adds code to handle relocation strategy RELOC_SPECIAL in
target-reloc.h and ARM specific code in arm.cc to handle relocation
types with odd-sizes or incontigious bits. Previously, all targets
used generic code to handle full 8/16/32/64 bit relocations. That did
not work on ARM and caused the Linux kernel to be linked incorrectly.
This patch adds a hook Sized_target::relocate_special_relocatable.
For reasons I do not understand, the hooks in Sized_target do not
follow the normal convention in gold for virtual functions involving a
public interface foo() and a protected implementation do_foo(). I
could avoid changing other back-ends and testfile.cc if I used the
normal convention but I follow the local convention in the
Sized_target class.
The patch was tested on x86_64 and ARM Linux with the full gold test suite.
-Doug
2010-05-25 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.
* i386.cc (Target_i386::relocate_special_relocatable): New method.
* powerpc.cc (Target_powerpc::relocate_special_relocatable): Same.
* sparc.cc (Target_sparc::relocate_speical_relocatable): Same.
* target-reloc.h (relocate_for_relocatable): Let target handle
relocation strategy Relocatable_relocs::RELOC_SPECIAL.
* target.h (Sized_target::relocate_special_relocatable): New method.
* x86_64.cc (Target_x86_64::relocate_special_relocatable): Same.
* testsuite/testfile.cc (Target_test::relocate_special_relocatable):
Same.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.105
diff -u -u -p -r1.105 arm.cc
--- gold/arm.cc 23 May 2010 07:43:39 -0000 1.105
+++ gold/arm.cc 25 May 2010 03:07:54 -0000
@@ -1956,6 +1956,79 @@ class Arm_output_data_got : public Outpu
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<3
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_
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_
// 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>::thum
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>::thum
// 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))
- || (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)))
+ 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))))
{
Arm_address unadjusted_branch_target = psymval->value(object, 0);
@@ -8919,7 +9013,7 @@ Target_arm<big_endian>::scan_relocatable
{
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_rel
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
Index: gold/i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.117
diff -u -u -p -r1.117 i386.cc
--- gold/i386.cc 11 Mar 2010 01:18:26 -0000 1.117
+++ gold/i386.cc 25 May 2010 03:07:54 -0000
@@ -149,6 +149,19 @@ class Target_i386 : public Target_freebs
unsigned char* reloc_view,
section_size_type reloc_view_size);
+ // Perform target-specific relocation in a relocatable link.
+ void
+ relocate_special_relocatable(const Relocate_info<32, false>*,
+ unsigned int, const unsigned char*, size_t,
+ Output_section*, off_t, unsigned char*,
+ elfcpp::Elf_types<32>::Elf_Addr,
+ section_size_type, unsigned char*)
+ {
+ // On this target, everything is done by target-indendepent code.
+ // We should not come here.
+ gold_unreachable();
+ }
+
// Return a string used to fill a code section with nops.
std::string
do_code_fill(section_size_type length) const;
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.29
diff -u -u -p -r1.29 powerpc.cc
--- gold/powerpc.cc 13 Feb 2010 02:04:20 -0000 1.29
+++ gold/powerpc.cc 25 May 2010 03:07:54 -0000
@@ -142,6 +142,19 @@ class Target_powerpc : public Sized_targ
unsigned char* reloc_view,
section_size_type reloc_view_size);
+ // Perform target-specific relocation in a relocatable link.
+ void
+ relocate_special_relocatable(const Relocate_info<size, big_endian>*,
+ unsigned int, const unsigned char*, size_t,
+ Output_section*, off_t, unsigned char*,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
+ section_size_type, unsigned char*)
+ {
+ // On this target, everything is done by target-indendepent code.
+ // We should not come here.
+ gold_unreachable();
+ }
+
// Return whether SYM is defined by the ABI.
bool
do_is_defined_by_abi(const Symbol* sym) const
Index: gold/sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.38
diff -u -u -p -r1.38 sparc.cc
--- gold/sparc.cc 10 Mar 2010 17:07:26 -0000 1.38
+++ gold/sparc.cc 25 May 2010 03:07:55 -0000
@@ -143,6 +143,20 @@ class Target_sparc : public Sized_target
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size);
+
+ // Perform target-specific relocation in a relocatable link.
+ void
+ relocate_special_relocatable(const Relocate_info<size, big_endian>*,
+ unsigned int, const unsigned char*, size_t,
+ Output_section*, off_t, unsigned char*,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
+ section_size_type, unsigned char*)
+ {
+ // On this target, everything is done by target-indendepent code.
+ // We should not come here.
+ gold_unreachable();
+ }
+
// Return whether SYM is defined by the ABI.
bool
do_is_defined_by_abi(const Symbol* sym) const
Index: gold/target-reloc.h
===================================================================
RCS file: /cvs/src/src/gold/target-reloc.h,v
retrieving revision 1.41
diff -u -u -p -r1.41 target-reloc.h
--- gold/target-reloc.h 20 Apr 2010 21:13:30 -0000 1.41
+++ gold/target-reloc.h 25 May 2010 03:07:55 -0000
@@ -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);
Index: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.47
diff -u -u -p -r1.47 target.h
--- gold/target.h 7 Apr 2010 21:42:22 -0000 1.47
+++ gold/target.h 25 May 2010 03:07:55 -0000
@@ -687,7 +687,23 @@ class Sized_target : public Target
section_size_type view_size,
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.
+ 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) = 0;
+
protected:
Sized_target(const Target::Target_info* pti)
: Target(pti)
Index: gold/x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.108
diff -u -u -p -r1.108 x86_64.cc
--- gold/x86_64.cc 20 Apr 2010 21:13:30 -0000 1.108
+++ gold/x86_64.cc 25 May 2010 03:07:55 -0000
@@ -164,6 +164,19 @@ class Target_x86_64 : public Target_free
unsigned char* reloc_view,
section_size_type reloc_view_size);
+ // Perform target-specific relocation in a relocatable link.
+ void
+ relocate_special_relocatable(const Relocate_info<64, false>*,
+ unsigned int, const unsigned char*, size_t,
+ Output_section*, off_t, unsigned char*,
+ elfcpp::Elf_types<64>::Elf_Addr,
+ section_size_type, unsigned char*)
+ {
+ // On this target, everything is done by target-indendepent code.
+ // We should not come here.
+ gold_unreachable();
+ }
+
// Return a string used to fill a code section with nops.
std::string
do_code_fill(section_size_type length) const;
Index: gold/testsuite/testfile.cc
===================================================================
RCS file: /cvs/src/src/gold/testsuite/testfile.cc,v
retrieving revision 1.18
diff -u -u -p -r1.18 testfile.cc
--- gold/testsuite/testfile.cc 6 Dec 2009 02:49:46 -0000 1.18
+++ gold/testsuite/testfile.cc 25 May 2010 03:07:55 -0000
@@ -62,6 +62,15 @@ class Target_test : public Sized_target<
section_size_type, const Reloc_symbol_changes*)
{ ERROR("call to Target_test::relocate_section"); }
+
+ void
+ relocate_special_relocatable(const Relocate_info<size, big_endian>*,
+ unsigned int, const unsigned char*, size_t,
+ Output_section*, off_t, unsigned char*,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
+ section_size_type, unsigned char*)
+ { ERROR("call to Target_test::relocate_special_relocatable"); }
+
void
scan_relocatable_relocs(Symbol_table*, Layout*,
Sized_relobj<size, big_endian>*, unsigned int,
More information about the Binutils
mailing list