Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: third_party/binutils/long-plt.patch

Issue 1537083003: Gold: Patch linker to implement --long-plt flag. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/binutils/build-all.sh ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/binutils/long-plt.patch
diff --git a/third_party/binutils/long-plt.patch b/third_party/binutils/long-plt.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9132377efcff82efa9e8a6d4304ae3c23da176e3
--- /dev/null
+++ b/third_party/binutils/long-plt.patch
@@ -0,0 +1,232 @@
+commit ee8713f5cfc38be0e92d78f2afbc77d701ef189d
+Author: Peter Collingbourne <pcc@google.com>
+Date: Thu Dec 17 16:50:35 2015 -0800
+
+ Implement --long-plt flag (ARM only).
+
+ 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.
+
+diff --git a/gold/arm.cc b/gold/arm.cc
+index 6c472bb..a10d785 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;
+@@ -2532,7 +2535,12 @@ class Target_arm : public Sized_target<32, big_endian>
+ virtual Output_data_plt_arm<big_endian>*
+ do_make_data_plt(Layout* layout, Output_data_space* got_plt)
+ {
+- return new Output_data_plt_arm_standard<big_endian>(layout, got_plt);
++ if (parameters->options().long_plt())
++ return new Output_data_plt_arm_long<big_endian>(
++ layout, got_plt);
++ else
++ return new Output_data_plt_arm_short<big_endian>(
++ layout, got_plt);
+ }
+
+ private:
+@@ -7382,29 +7390,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.
+@@ -7432,7 +7425,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] - .
+@@ -7441,9 +7434,37 @@ 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>
++class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endian>
++{
++ public:
++ Output_data_plt_arm_short(Layout* layout,
++ Output_data_space* got_plt)
++ : Output_data_plt_arm_standard<big_endian>(layout, got_plt)
++ { }
++
++ 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_standard<big_endian>::plt_entry[3] =
++const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] =
+ {
+ 0xe28fc600, // add ip, pc, #0xNN00000
+ 0xe28cca00, // add ip, ip, #0xNN000
+@@ -7452,7 +7473,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,
+@@ -7461,8 +7482,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);
+@@ -7471,6 +7493,66 @@ 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,
++ Output_data_space* got_plt)
++ : Output_data_plt_arm_standard<big_endian>(layout, got_plt)
++ { }
++
++ 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 cf3b705..5bd93b1e 100644
+--- a/gold/options.h
++++ b/gold/options.h
+@@ -826,6 +826,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);
+
« no previous file with comments | « third_party/binutils/build-all.sh ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698