public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] gold: Implement --long-plt flag.
@ 2015-11-20 23:46 Peter Collingbourne
  2015-12-02 18:17 ` Peter Collingbourne
  2015-12-17  0:42 ` Cary Coutant
  0 siblings, 2 replies; 6+ messages in thread
From: Peter Collingbourne @ 2015-11-20 23:46 UTC (permalink / raw)
  To: binutils; +Cc: Peter Collingbourne

gold/
    PR gold/18780
    * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based
    on value of --long-plt flag.
    (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to
    Output_data_plt_arm_short.
    (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise.
    (Output_data_plt_arm_standard::plt_entry): Likewise.
    (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix
    variable reference.
    (Output_data_plt_arm_short): New class.
    (Output_data_plt_arm_long): New class.
    * options.h (General_options): Define --long-plt flag.
---
 gold/arm.cc    | 124 +++++++++++++++++++++++++++++++++++++++++++++++----------
 gold/options.h |   4 ++
 2 files changed, 108 insertions(+), 20 deletions(-)

diff --git a/gold/arm.cc b/gold/arm.cc
index 4a6d414..2381442 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -62,7 +62,10 @@ template<bool big_endian>
 class Output_data_plt_arm;
 
 template<bool big_endian>
-class Output_data_plt_arm_standard;
+class Output_data_plt_arm_short;
+
+template<bool big_endian>
+class Output_data_plt_arm_long;
 
 template<bool big_endian>
 class Stub_table;
@@ -2555,7 +2558,11 @@ class Target_arm : public Sized_target<32, big_endian>
 		   Output_data_space* got_irelative)
   {
     gold_assert(got_plt != NULL && got_irelative != NULL);
-    return new Output_data_plt_arm_standard<big_endian>(
+    if (parameters->options().long_plt())
+      return new Output_data_plt_arm_long<big_endian>(
+	layout, got, got_plt, got_irelative);
+    else
+      return new Output_data_plt_arm_short<big_endian>(
 	layout, got, got_plt, got_irelative);
   }
 
@@ -7719,29 +7726,14 @@ class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
   do_first_plt_entry_offset() const
   { return sizeof(first_plt_entry); }
 
-  // Return the size of a PLT entry.
-  virtual unsigned int
-  do_get_plt_entry_size() const
-  { return sizeof(plt_entry); }
-
   virtual void
   do_fill_first_plt_entry(unsigned char* pov,
 			  Arm_address got_address,
 			  Arm_address plt_address);
 
-  virtual void
-  do_fill_plt_entry(unsigned char* pov,
-		    Arm_address got_address,
-		    Arm_address plt_address,
-		    unsigned int got_offset,
-		    unsigned int plt_offset);
-
  private:
   // Template for the first PLT entry.
   static const uint32_t first_plt_entry[5];
-
-  // Template for subsequent PLT entries.
-  static const uint32_t plt_entry[3];
 };
 
 // ARM PLTs.
@@ -7769,7 +7761,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
 {
   // Write first PLT entry.  All but the last word are constants.
   const size_t num_first_plt_words = (sizeof(first_plt_entry)
-				      / sizeof(plt_entry[0]));
+				      / sizeof(first_plt_entry[0]));
   for (size_t i = 0; i < num_first_plt_words - 1; i++)
     elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
   // Last word in first PLT entry is &GOT[0] - .
@@ -7778,9 +7770,39 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
 }
 
 // Subsequent entries in the PLT.
+// This class generates short (12-byte) entries, for displacements up to 2^28.
 
 template<bool big_endian>
-const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
+class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endian>
+{
+ public:
+  Output_data_plt_arm_short(Layout* layout,
+			    Arm_output_data_got<big_endian>* got,
+			    Output_data_space* got_plt,
+			    Output_data_space* got_irelative)
+    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
+  { }
+
+ protected:
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Arm_address got_address,
+		    Arm_address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset);
+
+ private:
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[3];
+};
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] =
 {
   0xe28fc600,	// add   ip, pc, #0xNN00000
   0xe28cca00,	// add   ip, ip, #0xNN000
@@ -7789,7 +7811,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
 
 template<bool big_endian>
 void
-Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
+Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
     unsigned char* pov,
     Arm_address got_address,
     Arm_address plt_address,
@@ -7808,6 +7830,68 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
   elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
 }
 
+// This class generates long (16-byte) entries, for arbitrary displacements.
+
+template<bool big_endian>
+class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian>
+{
+ public:
+  Output_data_plt_arm_long(Layout* layout,
+			   Arm_output_data_got<big_endian>* got,
+			   Output_data_space* got_plt,
+			   Output_data_space* got_irelative)
+    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
+  { }
+
+ protected:
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Arm_address got_address,
+		    Arm_address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset);
+
+ private:
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[4];
+};
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_long<big_endian>::plt_entry[4] =
+{
+  0xe28fc200,	// add   ip, pc, #0xN0000000
+  0xe28cc600,	// add   ip, ip, #0xNN00000
+  0xe28cca00,	// add   ip, ip, #0xNN000
+  0xe5bcf000,	// ldr   pc, [ip, #0xNNN]!
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_long<big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset)
+{
+  int32_t offset = ((got_address + got_offset)
+		    - (plt_address + plt_offset + 8));
+
+  uint32_t plt_insn0 = plt_entry[0] | (offset >> 28);
+  elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
+  uint32_t plt_insn1 = plt_entry[1] | ((offset >> 20) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
+  uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+  uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3);
+}
+
 // Write out the PLT.  This uses the hand-coded instructions above,
 // and adjusts them as needed.  This is all specified by the arm ELF
 // Processor Supplement.
diff --git a/gold/options.h b/gold/options.h
index ffc44e6..d83ea54 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -834,6 +834,10 @@ class General_options
 		    "veneer"),
 		 NULL);
 
+  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
+	      N_("(ARM only) Generate long PLT entries."),
+	      N_("(ARM only) Do not generate long PLT entries."));
+
   DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false,
 	      N_("Ignored"), NULL);
 
-- 
2.6.0.rc2.230.g3dd15c0

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

* Re: [PATCH] gold: Implement --long-plt flag.
  2015-11-20 23:46 [PATCH] gold: Implement --long-plt flag Peter Collingbourne
@ 2015-12-02 18:17 ` Peter Collingbourne
  2015-12-14 18:28   ` Peter Collingbourne
  2015-12-17  0:42 ` Cary Coutant
  1 sibling, 1 reply; 6+ messages in thread
From: Peter Collingbourne @ 2015-12-02 18:17 UTC (permalink / raw)
  To: binutils; +Cc: ccoutant

Ping.

On Fri, Nov 20, 2015 at 3:45 PM, Peter Collingbourne <pcc@google.com> wrote:
> gold/
>     PR gold/18780
>     * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based
>     on value of --long-plt flag.
>     (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to
>     Output_data_plt_arm_short.
>     (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise.
>     (Output_data_plt_arm_standard::plt_entry): Likewise.
>     (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix
>     variable reference.
>     (Output_data_plt_arm_short): New class.
>     (Output_data_plt_arm_long): New class.
>     * options.h (General_options): Define --long-plt flag.
> ---
>  gold/arm.cc    | 124 +++++++++++++++++++++++++++++++++++++++++++++++----------
>  gold/options.h |   4 ++
>  2 files changed, 108 insertions(+), 20 deletions(-)
>
> diff --git a/gold/arm.cc b/gold/arm.cc
> index 4a6d414..2381442 100644
> --- a/gold/arm.cc
> +++ b/gold/arm.cc
> @@ -62,7 +62,10 @@ template<bool big_endian>
>  class Output_data_plt_arm;
>
>  template<bool big_endian>
> -class Output_data_plt_arm_standard;
> +class Output_data_plt_arm_short;
> +
> +template<bool big_endian>
> +class Output_data_plt_arm_long;
>
>  template<bool big_endian>
>  class Stub_table;
> @@ -2555,7 +2558,11 @@ class Target_arm : public Sized_target<32, big_endian>
>                    Output_data_space* got_irelative)
>    {
>      gold_assert(got_plt != NULL && got_irelative != NULL);
> -    return new Output_data_plt_arm_standard<big_endian>(
> +    if (parameters->options().long_plt())
> +      return new Output_data_plt_arm_long<big_endian>(
> +       layout, got, got_plt, got_irelative);
> +    else
> +      return new Output_data_plt_arm_short<big_endian>(
>         layout, got, got_plt, got_irelative);
>    }
>
> @@ -7719,29 +7726,14 @@ class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
>    do_first_plt_entry_offset() const
>    { return sizeof(first_plt_entry); }
>
> -  // Return the size of a PLT entry.
> -  virtual unsigned int
> -  do_get_plt_entry_size() const
> -  { return sizeof(plt_entry); }
> -
>    virtual void
>    do_fill_first_plt_entry(unsigned char* pov,
>                           Arm_address got_address,
>                           Arm_address plt_address);
>
> -  virtual void
> -  do_fill_plt_entry(unsigned char* pov,
> -                   Arm_address got_address,
> -                   Arm_address plt_address,
> -                   unsigned int got_offset,
> -                   unsigned int plt_offset);
> -
>   private:
>    // Template for the first PLT entry.
>    static const uint32_t first_plt_entry[5];
> -
> -  // Template for subsequent PLT entries.
> -  static const uint32_t plt_entry[3];
>  };
>
>  // ARM PLTs.
> @@ -7769,7 +7761,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
>  {
>    // Write first PLT entry.  All but the last word are constants.
>    const size_t num_first_plt_words = (sizeof(first_plt_entry)
> -                                     / sizeof(plt_entry[0]));
> +                                     / sizeof(first_plt_entry[0]));
>    for (size_t i = 0; i < num_first_plt_words - 1; i++)
>      elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
>    // Last word in first PLT entry is &GOT[0] - .
> @@ -7778,9 +7770,39 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
>  }
>
>  // Subsequent entries in the PLT.
> +// This class generates short (12-byte) entries, for displacements up to 2^28.
>
>  template<bool big_endian>
> -const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
> +class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endian>
> +{
> + public:
> +  Output_data_plt_arm_short(Layout* layout,
> +                           Arm_output_data_got<big_endian>* got,
> +                           Output_data_space* got_plt,
> +                           Output_data_space* got_irelative)
> +    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
> +  { }
> +
> + protected:
> +  // Return the size of a PLT entry.
> +  virtual unsigned int
> +  do_get_plt_entry_size() const
> +  { return sizeof(plt_entry); }
> +
> +  virtual void
> +  do_fill_plt_entry(unsigned char* pov,
> +                   Arm_address got_address,
> +                   Arm_address plt_address,
> +                   unsigned int got_offset,
> +                   unsigned int plt_offset);
> +
> + private:
> +  // Template for subsequent PLT entries.
> +  static const uint32_t plt_entry[3];
> +};
> +
> +template<bool big_endian>
> +const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] =
>  {
>    0xe28fc600,  // add   ip, pc, #0xNN00000
>    0xe28cca00,  // add   ip, ip, #0xNN000
> @@ -7789,7 +7811,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
>
>  template<bool big_endian>
>  void
> -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
> +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
>      unsigned char* pov,
>      Arm_address got_address,
>      Arm_address plt_address,
> @@ -7808,6 +7830,68 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
>    elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
>  }
>
> +// This class generates long (16-byte) entries, for arbitrary displacements.
> +
> +template<bool big_endian>
> +class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian>
> +{
> + public:
> +  Output_data_plt_arm_long(Layout* layout,
> +                          Arm_output_data_got<big_endian>* got,
> +                          Output_data_space* got_plt,
> +                          Output_data_space* got_irelative)
> +    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
> +  { }
> +
> + protected:
> +  // Return the size of a PLT entry.
> +  virtual unsigned int
> +  do_get_plt_entry_size() const
> +  { return sizeof(plt_entry); }
> +
> +  virtual void
> +  do_fill_plt_entry(unsigned char* pov,
> +                   Arm_address got_address,
> +                   Arm_address plt_address,
> +                   unsigned int got_offset,
> +                   unsigned int plt_offset);
> +
> + private:
> +  // Template for subsequent PLT entries.
> +  static const uint32_t plt_entry[4];
> +};
> +
> +template<bool big_endian>
> +const uint32_t Output_data_plt_arm_long<big_endian>::plt_entry[4] =
> +{
> +  0xe28fc200,  // add   ip, pc, #0xN0000000
> +  0xe28cc600,  // add   ip, ip, #0xNN00000
> +  0xe28cca00,  // add   ip, ip, #0xNN000
> +  0xe5bcf000,  // ldr   pc, [ip, #0xNNN]!
> +};
> +
> +template<bool big_endian>
> +void
> +Output_data_plt_arm_long<big_endian>::do_fill_plt_entry(
> +    unsigned char* pov,
> +    Arm_address got_address,
> +    Arm_address plt_address,
> +    unsigned int got_offset,
> +    unsigned int plt_offset)
> +{
> +  int32_t offset = ((got_address + got_offset)
> +                   - (plt_address + plt_offset + 8));
> +
> +  uint32_t plt_insn0 = plt_entry[0] | (offset >> 28);
> +  elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
> +  uint32_t plt_insn1 = plt_entry[1] | ((offset >> 20) & 0xff);
> +  elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
> +  uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff);
> +  elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
> +  uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff);
> +  elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3);
> +}
> +
>  // Write out the PLT.  This uses the hand-coded instructions above,
>  // and adjusts them as needed.  This is all specified by the arm ELF
>  // Processor Supplement.
> diff --git a/gold/options.h b/gold/options.h
> index ffc44e6..d83ea54 100644
> --- a/gold/options.h
> +++ b/gold/options.h
> @@ -834,6 +834,10 @@ class General_options
>                     "veneer"),
>                  NULL);
>
> +  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
> +             N_("(ARM only) Generate long PLT entries."),
> +             N_("(ARM only) Do not generate long PLT entries."));
> +
>    DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false,
>               N_("Ignored"), NULL);
>
> --
> 2.6.0.rc2.230.g3dd15c0
>

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

* Re: [PATCH] gold: Implement --long-plt flag.
  2015-12-02 18:17 ` Peter Collingbourne
@ 2015-12-14 18:28   ` Peter Collingbourne
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Collingbourne @ 2015-12-14 18:28 UTC (permalink / raw)
  To: binutils; +Cc: Cary Coutant

Ping^2.

On Wed, Dec 2, 2015 at 10:17 AM, Peter Collingbourne <pcc@google.com> wrote:
> Ping.
>
> On Fri, Nov 20, 2015 at 3:45 PM, Peter Collingbourne <pcc@google.com> wrote:
>> gold/
>>     PR gold/18780
>>     * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based
>>     on value of --long-plt flag.
>>     (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to
>>     Output_data_plt_arm_short.
>>     (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise.
>>     (Output_data_plt_arm_standard::plt_entry): Likewise.
>>     (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix
>>     variable reference.
>>     (Output_data_plt_arm_short): New class.
>>     (Output_data_plt_arm_long): New class.
>>     * options.h (General_options): Define --long-plt flag.
>> ---
>>  gold/arm.cc    | 124 +++++++++++++++++++++++++++++++++++++++++++++++----------
>>  gold/options.h |   4 ++
>>  2 files changed, 108 insertions(+), 20 deletions(-)
>>
>> diff --git a/gold/arm.cc b/gold/arm.cc
>> index 4a6d414..2381442 100644
>> --- a/gold/arm.cc
>> +++ b/gold/arm.cc
>> @@ -62,7 +62,10 @@ template<bool big_endian>
>>  class Output_data_plt_arm;
>>
>>  template<bool big_endian>
>> -class Output_data_plt_arm_standard;
>> +class Output_data_plt_arm_short;
>> +
>> +template<bool big_endian>
>> +class Output_data_plt_arm_long;
>>
>>  template<bool big_endian>
>>  class Stub_table;
>> @@ -2555,7 +2558,11 @@ class Target_arm : public Sized_target<32, big_endian>
>>                    Output_data_space* got_irelative)
>>    {
>>      gold_assert(got_plt != NULL && got_irelative != NULL);
>> -    return new Output_data_plt_arm_standard<big_endian>(
>> +    if (parameters->options().long_plt())
>> +      return new Output_data_plt_arm_long<big_endian>(
>> +       layout, got, got_plt, got_irelative);
>> +    else
>> +      return new Output_data_plt_arm_short<big_endian>(
>>         layout, got, got_plt, got_irelative);
>>    }
>>
>> @@ -7719,29 +7726,14 @@ class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
>>    do_first_plt_entry_offset() const
>>    { return sizeof(first_plt_entry); }
>>
>> -  // Return the size of a PLT entry.
>> -  virtual unsigned int
>> -  do_get_plt_entry_size() const
>> -  { return sizeof(plt_entry); }
>> -
>>    virtual void
>>    do_fill_first_plt_entry(unsigned char* pov,
>>                           Arm_address got_address,
>>                           Arm_address plt_address);
>>
>> -  virtual void
>> -  do_fill_plt_entry(unsigned char* pov,
>> -                   Arm_address got_address,
>> -                   Arm_address plt_address,
>> -                   unsigned int got_offset,
>> -                   unsigned int plt_offset);
>> -
>>   private:
>>    // Template for the first PLT entry.
>>    static const uint32_t first_plt_entry[5];
>> -
>> -  // Template for subsequent PLT entries.
>> -  static const uint32_t plt_entry[3];
>>  };
>>
>>  // ARM PLTs.
>> @@ -7769,7 +7761,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
>>  {
>>    // Write first PLT entry.  All but the last word are constants.
>>    const size_t num_first_plt_words = (sizeof(first_plt_entry)
>> -                                     / sizeof(plt_entry[0]));
>> +                                     / sizeof(first_plt_entry[0]));
>>    for (size_t i = 0; i < num_first_plt_words - 1; i++)
>>      elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
>>    // Last word in first PLT entry is &GOT[0] - .
>> @@ -7778,9 +7770,39 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
>>  }
>>
>>  // Subsequent entries in the PLT.
>> +// This class generates short (12-byte) entries, for displacements up to 2^28.
>>
>>  template<bool big_endian>
>> -const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
>> +class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endian>
>> +{
>> + public:
>> +  Output_data_plt_arm_short(Layout* layout,
>> +                           Arm_output_data_got<big_endian>* got,
>> +                           Output_data_space* got_plt,
>> +                           Output_data_space* got_irelative)
>> +    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
>> +  { }
>> +
>> + protected:
>> +  // Return the size of a PLT entry.
>> +  virtual unsigned int
>> +  do_get_plt_entry_size() const
>> +  { return sizeof(plt_entry); }
>> +
>> +  virtual void
>> +  do_fill_plt_entry(unsigned char* pov,
>> +                   Arm_address got_address,
>> +                   Arm_address plt_address,
>> +                   unsigned int got_offset,
>> +                   unsigned int plt_offset);
>> +
>> + private:
>> +  // Template for subsequent PLT entries.
>> +  static const uint32_t plt_entry[3];
>> +};
>> +
>> +template<bool big_endian>
>> +const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] =
>>  {
>>    0xe28fc600,  // add   ip, pc, #0xNN00000
>>    0xe28cca00,  // add   ip, ip, #0xNN000
>> @@ -7789,7 +7811,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
>>
>>  template<bool big_endian>
>>  void
>> -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
>> +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
>>      unsigned char* pov,
>>      Arm_address got_address,
>>      Arm_address plt_address,
>> @@ -7808,6 +7830,68 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
>>    elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
>>  }
>>
>> +// This class generates long (16-byte) entries, for arbitrary displacements.
>> +
>> +template<bool big_endian>
>> +class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian>
>> +{
>> + public:
>> +  Output_data_plt_arm_long(Layout* layout,
>> +                          Arm_output_data_got<big_endian>* got,
>> +                          Output_data_space* got_plt,
>> +                          Output_data_space* got_irelative)
>> +    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
>> +  { }
>> +
>> + protected:
>> +  // Return the size of a PLT entry.
>> +  virtual unsigned int
>> +  do_get_plt_entry_size() const
>> +  { return sizeof(plt_entry); }
>> +
>> +  virtual void
>> +  do_fill_plt_entry(unsigned char* pov,
>> +                   Arm_address got_address,
>> +                   Arm_address plt_address,
>> +                   unsigned int got_offset,
>> +                   unsigned int plt_offset);
>> +
>> + private:
>> +  // Template for subsequent PLT entries.
>> +  static const uint32_t plt_entry[4];
>> +};
>> +
>> +template<bool big_endian>
>> +const uint32_t Output_data_plt_arm_long<big_endian>::plt_entry[4] =
>> +{
>> +  0xe28fc200,  // add   ip, pc, #0xN0000000
>> +  0xe28cc600,  // add   ip, ip, #0xNN00000
>> +  0xe28cca00,  // add   ip, ip, #0xNN000
>> +  0xe5bcf000,  // ldr   pc, [ip, #0xNNN]!
>> +};
>> +
>> +template<bool big_endian>
>> +void
>> +Output_data_plt_arm_long<big_endian>::do_fill_plt_entry(
>> +    unsigned char* pov,
>> +    Arm_address got_address,
>> +    Arm_address plt_address,
>> +    unsigned int got_offset,
>> +    unsigned int plt_offset)
>> +{
>> +  int32_t offset = ((got_address + got_offset)
>> +                   - (plt_address + plt_offset + 8));
>> +
>> +  uint32_t plt_insn0 = plt_entry[0] | (offset >> 28);
>> +  elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
>> +  uint32_t plt_insn1 = plt_entry[1] | ((offset >> 20) & 0xff);
>> +  elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
>> +  uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff);
>> +  elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
>> +  uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff);
>> +  elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3);
>> +}
>> +
>>  // Write out the PLT.  This uses the hand-coded instructions above,
>>  // and adjusts them as needed.  This is all specified by the arm ELF
>>  // Processor Supplement.
>> diff --git a/gold/options.h b/gold/options.h
>> index ffc44e6..d83ea54 100644
>> --- a/gold/options.h
>> +++ b/gold/options.h
>> @@ -834,6 +834,10 @@ class General_options
>>                     "veneer"),
>>                  NULL);
>>
>> +  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
>> +             N_("(ARM only) Generate long PLT entries."),
>> +             N_("(ARM only) Do not generate long PLT entries."));
>> +
>>    DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false,
>>               N_("Ignored"), NULL);
>>
>> --
>> 2.6.0.rc2.230.g3dd15c0
>>

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

* Re: [PATCH] gold: Implement --long-plt flag.
  2015-11-20 23:46 [PATCH] gold: Implement --long-plt flag Peter Collingbourne
  2015-12-02 18:17 ` Peter Collingbourne
@ 2015-12-17  0:42 ` Cary Coutant
  2015-12-17 20:33   ` Peter Collingbourne
  1 sibling, 1 reply; 6+ messages in thread
From: Cary Coutant @ 2015-12-17  0:42 UTC (permalink / raw)
  To: Peter Collingbourne; +Cc: Binutils

>  template<bool big_endian>
>  void
> -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
> +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
>      unsigned char* pov,
>      Arm_address got_address,
>      Arm_address plt_address,

Please fix this routine to issue an error message, suggesting the use
of --long-plt, if the offset overflows the standard PLT.

> +  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
> +             N_("(ARM only) Generate long PLT entries."),
> +             N_("(ARM only) Do not generate long PLT entries."));

Help strings should not end with periods. (Yeah, there are some already there.)

This is OK with those changes.

-cary

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

* Re: [PATCH] gold: Implement --long-plt flag.
  2015-12-17  0:42 ` Cary Coutant
@ 2015-12-17 20:33   ` Peter Collingbourne
  2015-12-18  0:56     ` Cary Coutant
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Collingbourne @ 2015-12-17 20:33 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

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

On Wed, Dec 16, 2015 at 4:42 PM, Cary Coutant <ccoutant@gmail.com> wrote:
>
> >  template<bool big_endian>
> >  void
> > -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
> > +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
> >      unsigned char* pov,
> >      Arm_address got_address,
> >      Arm_address plt_address,
>
> Please fix this routine to issue an error message, suggesting the use
> of --long-plt, if the offset overflows the standard PLT.
>
> > +  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
> > +             N_("(ARM only) Generate long PLT entries."),
> > +             N_("(ARM only) Do not generate long PLT entries."));
>
> Help strings should not end with periods. (Yeah, there are some already there.)
>
> This is OK with those changes.

Thanks, new patch is attached. Can you please commit for me?

Peter

[-- Attachment #2: 0001-gold-Implement-long-plt-flag.patch --]
[-- Type: text/x-patch, Size: 8196 bytes --]

From 484be7b3ff7564f1c28c2058eb30015a5246267d Mon Sep 17 00:00:00 2001
From: Peter Collingbourne <pcc@google.com>
Date: Thu, 19 Nov 2015 18:47:39 -0800
Subject: [PATCH] gold: Implement --long-plt flag.

gold/
    PR gold/18780
    * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based
    on value of --long-plt flag.
    (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to
    Output_data_plt_arm_short.
    (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise.
    (Output_data_plt_arm_standard::plt_entry): Likewise.
    (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix
    variable reference.
    (Output_data_plt_arm_short): New class.
    (Output_data_plt_arm_short::do_fill_plt_entry): Error out on too large
    PLT offsets instead of asserting.
    (Output_data_plt_arm_long): New class.
    * options.h (General_options): Define --long-plt flag.
---
 gold/arm.cc    | 127 +++++++++++++++++++++++++++++++++++++++++++++++----------
 gold/options.h |   4 ++
 2 files changed, 110 insertions(+), 21 deletions(-)

diff --git a/gold/arm.cc b/gold/arm.cc
index 33e8734..fc387bb 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -62,7 +62,10 @@ template<bool big_endian>
 class Output_data_plt_arm;
 
 template<bool big_endian>
-class Output_data_plt_arm_standard;
+class Output_data_plt_arm_short;
+
+template<bool big_endian>
+class Output_data_plt_arm_long;
 
 template<bool big_endian>
 class Stub_table;
@@ -2554,7 +2557,11 @@ class Target_arm : public Sized_target<32, big_endian>
 		   Output_data_space* got_irelative)
   {
     gold_assert(got_plt != NULL && got_irelative != NULL);
-    return new Output_data_plt_arm_standard<big_endian>(
+    if (parameters->options().long_plt())
+      return new Output_data_plt_arm_long<big_endian>(
+	layout, got, got_plt, got_irelative);
+    else
+      return new Output_data_plt_arm_short<big_endian>(
 	layout, got, got_plt, got_irelative);
   }
 
@@ -7715,29 +7722,14 @@ class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
   do_first_plt_entry_offset() const
   { return sizeof(first_plt_entry); }
 
-  // Return the size of a PLT entry.
-  virtual unsigned int
-  do_get_plt_entry_size() const
-  { return sizeof(plt_entry); }
-
   virtual void
   do_fill_first_plt_entry(unsigned char* pov,
 			  Arm_address got_address,
 			  Arm_address plt_address);
 
-  virtual void
-  do_fill_plt_entry(unsigned char* pov,
-		    Arm_address got_address,
-		    Arm_address plt_address,
-		    unsigned int got_offset,
-		    unsigned int plt_offset);
-
  private:
   // Template for the first PLT entry.
   static const uint32_t first_plt_entry[5];
-
-  // Template for subsequent PLT entries.
-  static const uint32_t plt_entry[3];
 };
 
 // ARM PLTs.
@@ -7765,7 +7757,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
 {
   // Write first PLT entry.  All but the last word are constants.
   const size_t num_first_plt_words = (sizeof(first_plt_entry)
-				      / sizeof(plt_entry[0]));
+				      / sizeof(first_plt_entry[0]));
   for (size_t i = 0; i < num_first_plt_words - 1; i++)
     elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
   // Last word in first PLT entry is &GOT[0] - .
@@ -7774,9 +7766,39 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
 }
 
 // Subsequent entries in the PLT.
+// This class generates short (12-byte) entries, for displacements up to 2^28.
 
 template<bool big_endian>
-const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
+class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endian>
+{
+ public:
+  Output_data_plt_arm_short(Layout* layout,
+			    Arm_output_data_got<big_endian>* got,
+			    Output_data_space* got_plt,
+			    Output_data_space* got_irelative)
+    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
+  { }
+
+ protected:
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Arm_address got_address,
+		    Arm_address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset);
+
+ private:
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[3];
+};
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] =
 {
   0xe28fc600,	// add   ip, pc, #0xNN00000
   0xe28cca00,	// add   ip, ip, #0xNN000
@@ -7785,7 +7807,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
 
 template<bool big_endian>
 void
-Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
+Output_data_plt_arm_short<big_endian>::do_fill_plt_entry(
     unsigned char* pov,
     Arm_address got_address,
     Arm_address plt_address,
@@ -7794,8 +7816,9 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
 {
   int32_t offset = ((got_address + got_offset)
 		    - (plt_address + plt_offset + 8));
+  if (offset < 0 || offset > 0x0fffffff)
+    gold_error(_("PLT offset too large, try linking with --long-plt"));
 
-  gold_assert(offset >= 0 && offset < 0x0fffffff);
   uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff);
   elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
   uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff);
@@ -7804,6 +7827,68 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
   elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
 }
 
+// This class generates long (16-byte) entries, for arbitrary displacements.
+
+template<bool big_endian>
+class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian>
+{
+ public:
+  Output_data_plt_arm_long(Layout* layout,
+			   Arm_output_data_got<big_endian>* got,
+			   Output_data_space* got_plt,
+			   Output_data_space* got_irelative)
+    : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelative)
+  { }
+
+ protected:
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Arm_address got_address,
+		    Arm_address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset);
+
+ private:
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[4];
+};
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_long<big_endian>::plt_entry[4] =
+{
+  0xe28fc200,	// add   ip, pc, #0xN0000000
+  0xe28cc600,	// add   ip, ip, #0xNN00000
+  0xe28cca00,	// add   ip, ip, #0xNN000
+  0xe5bcf000,	// ldr   pc, [ip, #0xNNN]!
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_long<big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset)
+{
+  int32_t offset = ((got_address + got_offset)
+		    - (plt_address + plt_offset + 8));
+
+  uint32_t plt_insn0 = plt_entry[0] | (offset >> 28);
+  elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
+  uint32_t plt_insn1 = plt_entry[1] | ((offset >> 20) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
+  uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+  uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3);
+}
+
 // Write out the PLT.  This uses the hand-coded instructions above,
 // and adjusts them as needed.  This is all specified by the arm ELF
 // Processor Supplement.
diff --git a/gold/options.h b/gold/options.h
index ffc44e6..8b5159f 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -834,6 +834,10 @@ class General_options
 		    "veneer"),
 		 NULL);
 
+  DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false,
+	      N_("(ARM only) Generate long PLT entries"),
+	      N_("(ARM only) Do not generate long PLT entries"));
+
   DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false,
 	      N_("Ignored"), NULL);
 
-- 
2.6.0.rc2.230.g3dd15c0


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

* Re: [PATCH] gold: Implement --long-plt flag.
  2015-12-17 20:33   ` Peter Collingbourne
@ 2015-12-18  0:56     ` Cary Coutant
  0 siblings, 0 replies; 6+ messages in thread
From: Cary Coutant @ 2015-12-18  0:56 UTC (permalink / raw)
  To: Peter Collingbourne; +Cc: Binutils

> Thanks, new patch is attached. Can you please commit for me?

Committed.

-cary

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

end of thread, other threads:[~2015-12-18  0:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-20 23:46 [PATCH] gold: Implement --long-plt flag Peter Collingbourne
2015-12-02 18:17 ` Peter Collingbourne
2015-12-14 18:28   ` Peter Collingbourne
2015-12-17  0:42 ` Cary Coutant
2015-12-17 20:33   ` Peter Collingbourne
2015-12-18  0:56     ` Cary Coutant

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