public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH][GOLD] Handle target specific relocatable relocation.
@ 2010-05-25  3:30 Doug Kwan (關振德)
  2010-05-25  4:33 ` Ian Lance Taylor
  2010-05-26  0:42 ` Ian Lance Taylor
  0 siblings, 2 replies; 3+ messages in thread
From: Doug Kwan (關振德) @ 2010-05-25  3:30 UTC (permalink / raw)
  To: Ian Lance Taylor, binutils

[-- Attachment #1: Type: text/plain, Size: 1890 bytes --]

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.

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 23799 bytes --]

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,

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][GOLD] Handle target specific relocatable relocation.
  2010-05-25  3:30 [PATCH][GOLD] Handle target specific relocatable relocation Doug Kwan (關振德)
@ 2010-05-25  4:33 ` Ian Lance Taylor
  2010-05-26  0:42 ` Ian Lance Taylor
  1 sibling, 0 replies; 3+ messages in thread
From: Ian Lance Taylor @ 2010-05-25  4:33 UTC (permalink / raw)
  To: Doug Kwan (關振德); +Cc: binutils

"Doug Kwan (關振德)" <dougkwan@google.com> writes:

> 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 haven't looked at your patch yet, but the reason for this is that
the Sized_target class is, by design, entirely abstract.  All the
methods are virtual and they are all either pure or crash.  There was
no need to separate the interface presented to others from the
interface supplied by the child class: Sized_target only has a child
class interface.

Ian

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][GOLD] Handle target specific relocatable relocation.
  2010-05-25  3:30 [PATCH][GOLD] Handle target specific relocatable relocation Doug Kwan (關振德)
  2010-05-25  4:33 ` Ian Lance Taylor
@ 2010-05-26  0:42 ` Ian Lance Taylor
  1 sibling, 0 replies; 3+ messages in thread
From: Ian Lance Taylor @ 2010-05-26  0:42 UTC (permalink / raw)
  To: Doug Kwan (關振德); +Cc: binutils

"Doug Kwan (關振德)" <dougkwan@google.com> writes:

> 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.



> +  // 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;

It's OK to make this simply { gold_unreachable(); } rather than making
it pure virtual.  That will make it the same as make_symbol and
resolve.  Then you don't have to change the other targets.

This is OK with that change.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-05-26  0:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-25  3:30 [PATCH][GOLD] Handle target specific relocatable relocation Doug Kwan (關振德)
2010-05-25  4:33 ` Ian Lance Taylor
2010-05-26  0:42 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).