[GOLD][PATCH] Relocate ARM stubs.

Doug Kwan (關振德) dougkwan@google.com
Mon Nov 9 16:46:00 GMT 2009


Hi,

    This patch enables relocation of stubs.  It also fixes a few
problems due to the recent change of not passing general options.

-Doug

2009-11-10  Doug Kwan  <dougkwan@google.com>

        * arm.cc (Arm_relobj::do_relocate_sections): Remove options parameter
        in method declaration.
        (Target_arm::relocate_stub): New method declaration.
        (Target_arm::default_target): Change to return a pointer instead of
        a const reference.
        (Reloc_stub::stub_type_for_reloc): Adjust for the change in
        Target_arm::default_target.
        (Arm_Relobj::do_relocate_sections): Remove options paramater in
        method definition.
        (Target_arm::relocate_section): Adjust view.
        (Target_arm::relocate_stub): New method definition.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.31
diff -u -p -r1.31 arm.cc
--- gold/arm.cc	9 Nov 2009 16:03:45 -0000	1.31
+++ gold/arm.cc	9 Nov 2009 16:34:54 -0000
@@ -972,8 +972,7 @@ class Arm_relobj : public Sized_relobj<3
                          Stringpool_template<char>*);
 
   void
-  do_relocate_sections(const General_options& options,
-		       const Symbol_table* symtab, const Layout* layout,
+  do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
 		       const unsigned char* pshdrs,
 		       typename Sized_relobj<32, big_endian>::Views* pivews);
 
@@ -1315,13 +1314,20 @@ class Target_arm : public Sized_target<3
 			 bool, const unsigned char*, Arm_address,
 			 section_size_type);
 
+  // Relocate a stub. 
+  void
+  relocate_stub(Reloc_stub*, const Relocate_info<32, big_endian>*,
+		Output_section*, unsigned char*, Arm_address,
+		section_size_type);
+ 
   // Get the default ARM target.
-  static const Target_arm<big_endian>&
+  static Target_arm<big_endian>*
   default_target()
   {
     gold_assert(parameters->target().machine_code() == elfcpp::EM_ARM
 		&& parameters->target().is_big_endian() == big_endian);
-    return static_cast<const Target_arm<big_endian>&>(parameters->target());
+    return static_cast<Target_arm<big_endian>*>(
+	     parameters->sized_target<32, big_endian>());
   }
 
   // Whether relocation type uses LSB to distinguish THUMB addresses.
@@ -2388,21 +2394,21 @@ Reloc_stub::stub_type_for_reloc(
   bool thumb_only;
   if (parameters->target().is_big_endian())
     {
-      const Target_arm<true>& big_endian_target =
+      const Target_arm<true>* big_endian_target =
 	Target_arm<true>::default_target();
-      may_use_blx = big_endian_target.may_use_blx();
-      should_force_pic_veneer = big_endian_target.should_force_pic_veneer();
-      thumb2 = big_endian_target.using_thumb2();
-      thumb_only = big_endian_target.using_thumb_only();
+      may_use_blx = big_endian_target->may_use_blx();
+      should_force_pic_veneer = big_endian_target->should_force_pic_veneer();
+      thumb2 = big_endian_target->using_thumb2();
+      thumb_only = big_endian_target->using_thumb_only();
     }
   else
     {
-      const Target_arm<false>& little_endian_target =
+      const Target_arm<false>* little_endian_target =
 	Target_arm<false>::default_target();
-      may_use_blx = little_endian_target.may_use_blx();
-      should_force_pic_veneer = little_endian_target.should_force_pic_veneer();
-      thumb2 = little_endian_target.using_thumb2();
-      thumb_only = little_endian_target.using_thumb_only();
+      may_use_blx = little_endian_target->may_use_blx();
+      should_force_pic_veneer = little_endian_target->should_force_pic_veneer();
+      thumb2 = little_endian_target->using_thumb2();
+      thumb_only = little_endian_target->using_thumb_only();
     }
 
   int64_t branch_offset = (int64_t)destination - location;
@@ -3380,15 +3386,14 @@ Arm_relobj<big_endian>::do_count_local_s
 template<bool big_endian>
 void
 Arm_relobj<big_endian>::do_relocate_sections(
-    const General_options& options,
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
     typename Sized_relobj<32, big_endian>::Views* pviews)
 {
   // Call parent to relocate sections.
-  Sized_relobj<32, big_endian>::do_relocate_sections(options, symtab, layout,
-						     pshdrs, pviews); 
+  Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs,
+						     pviews); 
 
   // We do not generate stubs if doing a relocatable link.
   if (parameters->options().relocatable())
@@ -3401,7 +3406,6 @@ Arm_relobj<big_endian>::do_relocate_sect
     Target_arm<big_endian>::default_target();
 
   Relocate_info<32, big_endian> relinfo;
-  relinfo.options = &options;
   relinfo.symtab = symtab;
   relinfo.layout = layout;
   relinfo.object = this;
@@ -4775,6 +4779,28 @@ Target_arm<big_endian>::relocate_section
   typedef typename Target_arm<big_endian>::Relocate Arm_relocate;
   gold_assert(sh_type == elfcpp::SHT_REL);
 
+  Arm_input_section<big_endian>* arm_input_section =
+    this->find_arm_input_section(relinfo->object, relinfo->data_shndx);
+
+  // This is an ARM input section and the view covers the whole output
+  // section.
+  if (arm_input_section != NULL)
+    {
+      gold_assert(needs_special_offset_handling);
+      Arm_address section_address = arm_input_section->address();
+      section_size_type section_size = arm_input_section->data_size();
+
+      gold_assert((arm_input_section->address() >= address)
+		  && ((arm_input_section->address()
+		       + arm_input_section->data_size())
+		      <= (address + view_size)));
+
+      off_t offset = section_address - address;
+      view += offset;
+      address += offset;
+      view_size = section_size;
+    }
+
   gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
 			 Arm_relocate>(
     relinfo,
@@ -5614,6 +5640,51 @@ Target_arm<big_endian>::do_relax(
   return any_stub_table_changed;
 }
 
+// Relocate a stub.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::relocate_stub(
+    Reloc_stub* stub,
+    const Relocate_info<32, big_endian>* relinfo,
+    Output_section* output_section,
+    unsigned char* view,
+    Arm_address address,
+    section_size_type view_size)
+{
+  Relocate relocate;
+  const Stub_template* stub_template = stub->stub_template();
+  for (size_t i = 0; i < stub_template->reloc_count(); i++)
+    {
+      size_t reloc_insn_index = stub_template->reloc_insn_index(i);
+      const Insn_template* insn = &stub_template->insns()[reloc_insn_index];
+
+      unsigned int r_type = insn->r_type();
+      section_size_type reloc_offset = stub_template->reloc_offset(i);
+      section_size_type reloc_size = insn->size();
+      gold_assert(reloc_offset + reloc_size <= view_size);
+
+      // This is the address of the stub destination.
+      Arm_address target = stub->reloc_target(i);
+      Symbol_value<32> symval;
+      symval.set_output_value(target);
+
+      // Synthesize a fake reloc just in case.  We don't have a symbol so
+      // we use 0.
+      unsigned char reloc_buffer[elfcpp::Elf_sizes<32>::rel_size];
+      memset(reloc_buffer, 0, sizeof(reloc_buffer));
+      elfcpp::Rel_write<32, big_endian> reloc_write(reloc_buffer);
+      reloc_write.put_r_offset(reloc_offset);
+      reloc_write.put_r_info(elfcpp::elf_r_info<32>(0, r_type));
+      elfcpp::Rel<32, big_endian> rel(reloc_buffer);
+
+      relocate.relocate(relinfo, this, output_section,
+			this->fake_relnum_for_stubs, rel, r_type,
+			NULL, &symval, view + reloc_offset,
+			address + reloc_offset, reloc_size);
+    }
+}
+
 // The selector for arm object files.
 
 template<bool big_endian>


More information about the Binutils mailing list