[PATCH][ARM] Handle --target1-abs, --target1-rel and --target2 options.

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


Hi,

    This patch adds handling of --target1-abs, --target2-rel and
--target2 options.  Previously we hard-coded the real relocation types
of R_ARM_TARGET1 and R_ARM_TARGET2.

-Doug

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

        * arm.cc (Target_arm::Target_arm): Move method definition outside of
        class definition.  Add code to handle --target1-rel, --target1-abs
        and --target2= options.
        (Target_arm::get_reloc_reloc_type): Change method to be non-static
        and const.
        (Target_arm::target1_is_rel_, Target_arm::target2_reloc_): New data
        member declaration.
        (Target_arm::Scan::local, Target_arm::Scan::global,
        Target_arm::Relocate::relocate,
        Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): Adjust
        call to Target_arm::get_real_reloc_type.
        (Target_arm::get_real_reloc_type): Use command line options to
        determine real types of R_ARM_TARGET1 and R_ARM_TARGET2.
        * options.h (--target1-rel, --target1-abs, --target2): New ARM-only
        options.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.33
diff -u -p -r1.33 arm.cc
--- gold/arm.cc	16 Nov 2009 03:39:11 -0000	1.33
+++ gold/arm.cc	16 Nov 2009 08:48:32 -0000
@@ -1142,14 +1142,7 @@ class Target_arm : public Sized_target<3
   // When were are relocating a stub, we pass this as the relocation number.
   static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1);
 
-  Target_arm()
-    : Sized_target<32, big_endian>(&arm_info),
-      got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
-      copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), stub_tables_(),
-      stub_factory_(Stub_factory::get_instance()),
-      may_use_blx_(true), should_force_pic_veneer_(false),
-      arm_input_section_map_()
-  { }
+  Target_arm();
 
   // Whether we can use BLX.
   bool
@@ -1290,8 +1283,8 @@ class Target_arm : public Sized_target<3
   }
 
   // Map platform-specific reloc types
-  static unsigned int
-  get_real_reloc_type (unsigned int r_type);
+  unsigned int
+  get_real_reloc_type (unsigned int r_type) const;
 
   //
   // Methods to support stub-generations.
@@ -1623,6 +1616,11 @@ class Target_arm : public Sized_target<3
   Stub_table_list stub_tables_;
   // Stub factory.
   const Stub_factory &stub_factory_;
+  // Whether R_ARM_TARGET1 maps to R_ARM_REL32 or R_ARM_ABS32.
+  bool target1_is_rel_;
+  // What R_ARM_TARGET2 maps to.  It should be one of R_ARM_REL32, R_ARM_ABS32
+  // and R_ARM_GOT_PREL.
+  unsigned int target2_reloc_;
   // Whether we can use BLX.
   bool may_use_blx_;
   // Whether we force PIC branch veneers.
@@ -2292,6 +2290,40 @@ Arm_relocate_functions<big_endian>::arm_
 	  ? This::STATUS_OVERFLOW : This::STATUS_OKAY);
 }
 
+template<bool big_endian>
+Target_arm<big_endian>::Target_arm()
+  : Sized_target<32, big_endian>(&arm_info),
+    got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
+    copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), stub_tables_(),
+    stub_factory_(Stub_factory::get_instance()), target1_is_rel_(false),
+    target2_reloc_(elfcpp::R_ARM_TARGET2), may_use_blx_(true),
+    should_force_pic_veneer_(false), arm_input_section_map_()
+{
+  // FIXME: This is not strictly compatible with ld, which allows both
+  // --target1-abs and --target-rel to be given.
+  if (parameters->options().user_set_target1_abs()
+      && parameters->options().user_set_target1_rel())
+    {
+      gold_error(N_("Cannot use both --target1-abs and --target1-rel."));
+    }
+  else if (parameters->options().user_set_target1_rel())
+    this->target1_is_rel_ = true;
+  else if (parameters->options().user_set_target1_abs())
+    this->target1_is_rel_ = false;
+
+  if (parameters->options().user_set_target2())
+    {
+      if (strcmp(parameters->options().target2(), "rel") == 0)
+	this->target2_reloc_ = elfcpp::R_ARM_REL32;
+      else if (strcmp(parameters->options().target2(), "abs") == 0)
+	this->target2_reloc_ = elfcpp::R_ARM_ABS32;
+      else if (strcmp(parameters->options().target2(), "got-rel") == 0)
+	this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL;
+      else
+	gold_unreachable();
+    }
+}
+
 // Get the GOT section, creating it if necessary.
 
 template<bool big_endian>
@@ -3969,7 +4001,7 @@ Target_arm<big_endian>::Scan::local(Symb
 				    unsigned int r_type,
 				    const elfcpp::Sym<32, big_endian>&)
 {
-  r_type = get_real_reloc_type(r_type);
+  r_type = target->get_real_reloc_type(r_type);
   switch (r_type)
     {
     case elfcpp::R_ARM_NONE:
@@ -4096,7 +4128,7 @@ Target_arm<big_endian>::Scan::global(Sym
 				     unsigned int r_type,
 				     Symbol* gsym)
 {
-  r_type = get_real_reloc_type(r_type);
+  r_type = target->get_real_reloc_type(r_type);
   switch (r_type)
     {
     case elfcpp::R_ARM_NONE:
@@ -4508,7 +4540,7 @@ Target_arm<big_endian>::Relocate::reloca
 {
   typedef Arm_relocate_functions<big_endian> Arm_relocate_functions;
 
-  r_type = get_real_reloc_type(r_type);
+  r_type = target->get_real_reloc_type(r_type);
 
   const Arm_relobj<big_endian>* object =
     Arm_relobj<big_endian>::as_arm_relobj(relinfo->object);
@@ -4957,7 +4989,9 @@ Target_arm<big_endian>::Relocatable_size
     unsigned int r_type,
     Relobj* object)
 {
-  r_type = get_real_reloc_type(r_type);
+  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)
     {
     case elfcpp::R_ARM_NONE:
@@ -5102,17 +5136,15 @@ Target_arm<big_endian>::do_dynsym_value(
 //
 template<bool big_endian>
 unsigned int
-Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
+Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type) const
 {
   switch (r_type)
     {
     case elfcpp::R_ARM_TARGET1:
-      // This is either R_ARM_ABS32 or R_ARM_REL32;
-      return elfcpp::R_ARM_ABS32;
+      return this->target1_is_rel_? elfcpp::R_ARM_REL32 : elfcpp::R_ARM_ABS32;
 
     case elfcpp::R_ARM_TARGET2:
-      // This can be any reloc type but ususally is R_ARM_GOT_PREL
-      return elfcpp::R_ARM_GOT_PREL;
+      return this->target2_reloc_;
 
     default:
       return r_type;
Index: gold/options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.117
diff -u -p -r1.117 options.h
--- gold/options.h	4 Nov 2009 01:24:41 -0000	1.117
+++ gold/options.h	16 Nov 2009 08:48:32 -0000
@@ -884,6 +884,17 @@ class General_options
   DEFINE_string(sysroot, options::TWO_DASHES, '\0', "",
                 N_("Set target system root directory"), N_("DIR"));
 
+  DEFINE_bool(target1_rel, options::TWO_DASHES, '\0', false,
+	      N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_REL32"),
+	      NULL);
+  DEFINE_bool(target1_abs, options::TWO_DASHES, '\0', false,
+	      N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_ABS32"),
+	      NULL);
+  DEFINE_enum(target2, options::TWO_DASHES, '\0', "default",
+	      N_("(ARM only) Set R_ARM_TARGET2 relocation type"),
+	      N_("[default, rel, abs, got-rel"),
+	      {"default", "rel", "abs", "got-rel"});
+
   DEFINE_bool(trace, options::TWO_DASHES, 't', false,
               N_("Print the name of each input file"), NULL);
 


More information about the Binutils mailing list