OLD | NEW |
1 commit ee8713f5cfc38be0e92d78f2afbc77d701ef189d | 1 commit ce3e49806d505721e0875e704de0b6fcba7660ed |
2 Author: Peter Collingbourne <pcc@google.com> | 2 Author: Peter Collingbourne <pcc@google.com> |
3 Date: Thu Dec 17 16:50:35 2015 -0800 | 3 Date: Thu Dec 17 16:50:35 2015 -0800 |
4 | 4 |
5 Implement --long-plt flag (ARM only). | 5 Implement --long-plt flag (ARM only). |
6 | 6 |
7 gold/ | 7 gold/ |
8 PR gold/18780 | 8 PR gold/18780 |
9 * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based | 9 * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based |
10 on value of --long-plt flag. | 10 on value of --long-plt flag. |
11 (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to | 11 (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to |
12 Output_data_plt_arm_short. | 12 Output_data_plt_arm_short. |
13 (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise. | 13 (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise. |
14 (Output_data_plt_arm_standard::plt_entry): Likewise. | 14 (Output_data_plt_arm_standard::plt_entry): Likewise. |
15 (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix | 15 (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix |
16 variable reference. | 16 variable reference. |
17 (Output_data_plt_arm_short): New class. | 17 (Output_data_plt_arm_short): New class. |
18 (Output_data_plt_arm_short::do_fill_plt_entry): Error out on too large | 18 (Output_data_plt_arm_short::do_fill_plt_entry): Error out on too large |
19 PLT offsets instead of asserting. | 19 PLT offsets instead of asserting. |
20 (Output_data_plt_arm_long): New class. | 20 (Output_data_plt_arm_long): New class. |
21 * options.h (General_options): Define --long-plt flag. | 21 * options.h (General_options): Define --long-plt flag. |
22 | 22 |
| 23 diff --git a/gold/ChangeLog b/gold/ChangeLog |
| 24 index d929cb7..07589c9 100644 |
| 25 --- a/gold/ChangeLog |
| 26 +++ b/gold/ChangeLog |
| 27 @@ -1,3 +1,20 @@ |
| 28 +2015-12-17 Peter Collingbourne <pcc@google.com> |
| 29 + |
| 30 + PR gold/18780 |
| 31 + * arm.cc (Target_arm::do_make_data_plt): Choose PLT generator based |
| 32 + on value of --long-plt flag. |
| 33 + (Output_data_plt_arm_standard::do_get_plt_entry_size): Moved to |
| 34 + Output_data_plt_arm_short. |
| 35 + (Output_data_plt_arm_standard::do_fill_plt_entry): Likewise. |
| 36 + (Output_data_plt_arm_standard::plt_entry): Likewise. |
| 37 + (Output_data_plt_arm_standard::do_fill_first_plt_entry): Fix |
| 38 + variable reference. |
| 39 + (Output_data_plt_arm_short): New class. |
| 40 + (Output_data_plt_arm_short::do_fill_plt_entry): Error out on too large |
| 41 + PLT offsets instead of asserting. |
| 42 + (Output_data_plt_arm_long): New class. |
| 43 + * options.h (General_options): Define --long-plt flag. |
| 44 + |
| 45 2015-12-16 Roland McGrath <mcgrathr@google.com> |
| 46 |
| 47 PR ld/17473 |
23 diff --git a/gold/arm.cc b/gold/arm.cc | 48 diff --git a/gold/arm.cc b/gold/arm.cc |
24 index 6c472bb..a10d785 100644 | 49 index 33e8734..fc387bb 100644 |
25 --- a/gold/arm.cc | 50 --- a/gold/arm.cc |
26 +++ b/gold/arm.cc | 51 +++ b/gold/arm.cc |
27 @@ -62,7 +62,10 @@ template<bool big_endian> | 52 @@ -62,7 +62,10 @@ template<bool big_endian> |
28 class Output_data_plt_arm; | 53 class Output_data_plt_arm; |
29 | 54 |
30 template<bool big_endian> | 55 template<bool big_endian> |
31 -class Output_data_plt_arm_standard; | 56 -class Output_data_plt_arm_standard; |
32 +class Output_data_plt_arm_short; | 57 +class Output_data_plt_arm_short; |
33 + | 58 + |
34 +template<bool big_endian> | 59 +template<bool big_endian> |
35 +class Output_data_plt_arm_long; | 60 +class Output_data_plt_arm_long; |
36 | 61 |
37 template<bool big_endian> | 62 template<bool big_endian> |
38 class Stub_table; | 63 class Stub_table; |
39 @@ -2532,7 +2535,12 @@ class Target_arm : public Sized_target<32, big_endian> | 64 @@ -2554,7 +2557,11 @@ class Target_arm : public Sized_target<32, big_endian> |
40 virtual Output_data_plt_arm<big_endian>* | 65 » » Output_data_space* got_irelative) |
41 do_make_data_plt(Layout* layout, Output_data_space* got_plt) | |
42 { | 66 { |
43 - return new Output_data_plt_arm_standard<big_endian>(layout, got_plt); | 67 gold_assert(got_plt != NULL && got_irelative != NULL); |
| 68 - return new Output_data_plt_arm_standard<big_endian>( |
44 + if (parameters->options().long_plt()) | 69 + if (parameters->options().long_plt()) |
45 + return new Output_data_plt_arm_long<big_endian>( | 70 + return new Output_data_plt_arm_long<big_endian>( |
46 +» layout, got_plt); | 71 +» layout, got, got_plt, got_irelative); |
47 + else | 72 + else |
48 + return new Output_data_plt_arm_short<big_endian>( | 73 + return new Output_data_plt_arm_short<big_endian>( |
49 +» layout, got_plt); | 74 » layout, got, got_plt, got_irelative); |
50 } | 75 } |
51 | 76 |
52 private: | 77 @@ -7715,29 +7722,14 @@ class Output_data_plt_arm_standard : public Output_data_
plt_arm<big_endian> |
53 @@ -7382,29 +7390,14 @@ class Output_data_plt_arm_standard : public Output_data_
plt_arm<big_endian> | |
54 do_first_plt_entry_offset() const | 78 do_first_plt_entry_offset() const |
55 { return sizeof(first_plt_entry); } | 79 { return sizeof(first_plt_entry); } |
56 | 80 |
57 - // Return the size of a PLT entry. | 81 - // Return the size of a PLT entry. |
58 - virtual unsigned int | 82 - virtual unsigned int |
59 - do_get_plt_entry_size() const | 83 - do_get_plt_entry_size() const |
60 - { return sizeof(plt_entry); } | 84 - { return sizeof(plt_entry); } |
61 - | 85 - |
62 virtual void | 86 virtual void |
63 do_fill_first_plt_entry(unsigned char* pov, | 87 do_fill_first_plt_entry(unsigned char* pov, |
64 Arm_address got_address, | 88 Arm_address got_address, |
65 Arm_address plt_address); | 89 Arm_address plt_address); |
66 | 90 |
67 - virtual void | 91 - virtual void |
68 - do_fill_plt_entry(unsigned char* pov, | 92 - do_fill_plt_entry(unsigned char* pov, |
69 - Arm_address got_address, | 93 - Arm_address got_address, |
70 - Arm_address plt_address, | 94 - Arm_address plt_address, |
71 - unsigned int got_offset, | 95 - unsigned int got_offset, |
72 - unsigned int plt_offset); | 96 - unsigned int plt_offset); |
73 - | 97 - |
74 private: | 98 private: |
75 // Template for the first PLT entry. | 99 // Template for the first PLT entry. |
76 static const uint32_t first_plt_entry[5]; | 100 static const uint32_t first_plt_entry[5]; |
77 - | 101 - |
78 - // Template for subsequent PLT entries. | 102 - // Template for subsequent PLT entries. |
79 - static const uint32_t plt_entry[3]; | 103 - static const uint32_t plt_entry[3]; |
80 }; | 104 }; |
81 | 105 |
82 // ARM PLTs. | 106 // ARM PLTs. |
83 @@ -7432,7 +7425,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_pl
t_entry( | 107 @@ -7765,7 +7757,7 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_pl
t_entry( |
84 { | 108 { |
85 // Write first PLT entry. All but the last word are constants. | 109 // Write first PLT entry. All but the last word are constants. |
86 const size_t num_first_plt_words = (sizeof(first_plt_entry) | 110 const size_t num_first_plt_words = (sizeof(first_plt_entry) |
87 - / sizeof(plt_entry[0])); | 111 - / sizeof(plt_entry[0])); |
88 + / sizeof(first_plt_entry[0])); | 112 + / sizeof(first_plt_entry[0])); |
89 for (size_t i = 0; i < num_first_plt_words - 1; i++) | 113 for (size_t i = 0; i < num_first_plt_words - 1; i++) |
90 elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]); | 114 elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]); |
91 // Last word in first PLT entry is &GOT[0] - . | 115 // Last word in first PLT entry is &GOT[0] - . |
92 @@ -7441,9 +7434,37 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_p
lt_entry( | 116 @@ -7774,9 +7766,39 @@ Output_data_plt_arm_standard<big_endian>::do_fill_first_p
lt_entry( |
93 } | 117 } |
94 | 118 |
95 // Subsequent entries in the PLT. | 119 // Subsequent entries in the PLT. |
96 +// This class generates short (12-byte) entries, for displacements up to 2^28. | 120 +// This class generates short (12-byte) entries, for displacements up to 2^28. |
97 + | 121 |
98 +template<bool big_endian> | 122 template<bool big_endian> |
| 123 -const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] = |
99 +class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endia
n> | 124 +class Output_data_plt_arm_short : public Output_data_plt_arm_standard<big_endia
n> |
100 +{ | 125 +{ |
101 + public: | 126 + public: |
102 + Output_data_plt_arm_short(Layout* layout, | 127 + Output_data_plt_arm_short(Layout* layout, |
103 +» » » Output_data_space* got_plt) | 128 +» » » Arm_output_data_got<big_endian>* got, |
104 + : Output_data_plt_arm_standard<big_endian>(layout, got_plt) | 129 +» » » Output_data_space* got_plt, |
| 130 +» » » Output_data_space* got_irelative) |
| 131 + : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelat
ive) |
105 + { } | 132 + { } |
106 + | 133 + |
107 + protected: | 134 + protected: |
108 + // Return the size of a PLT entry. | 135 + // Return the size of a PLT entry. |
109 + virtual unsigned int | 136 + virtual unsigned int |
110 + do_get_plt_entry_size() const | 137 + do_get_plt_entry_size() const |
111 + { return sizeof(plt_entry); } | 138 + { return sizeof(plt_entry); } |
112 + | 139 + |
113 + virtual void | 140 + virtual void |
114 + do_fill_plt_entry(unsigned char* pov, | 141 + do_fill_plt_entry(unsigned char* pov, |
115 + Arm_address got_address, | 142 + Arm_address got_address, |
116 + Arm_address plt_address, | 143 + Arm_address plt_address, |
117 + unsigned int got_offset, | 144 + unsigned int got_offset, |
118 + unsigned int plt_offset); | 145 + unsigned int plt_offset); |
119 + | 146 + |
120 + private: | 147 + private: |
121 + // Template for subsequent PLT entries. | 148 + // Template for subsequent PLT entries. |
122 + static const uint32_t plt_entry[3]; | 149 + static const uint32_t plt_entry[3]; |
123 +}; | 150 +}; |
124 | 151 + |
125 template<bool big_endian> | 152 +template<bool big_endian> |
126 -const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] = | |
127 +const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] = | 153 +const uint32_t Output_data_plt_arm_short<big_endian>::plt_entry[3] = |
128 { | 154 { |
129 0xe28fc600, // add ip, pc, #0xNN00000 | 155 0xe28fc600, // add ip, pc, #0xNN00000 |
130 0xe28cca00, // add ip, ip, #0xNN000 | 156 0xe28cca00, // add ip, ip, #0xNN000 |
131 @@ -7452,7 +7473,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::p
lt_entry[3] = | 157 @@ -7785,7 +7807,7 @@ const uint32_t Output_data_plt_arm_standard<big_endian>::p
lt_entry[3] = |
132 | 158 |
133 template<bool big_endian> | 159 template<bool big_endian> |
134 void | 160 void |
135 -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry( | 161 -Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry( |
136 +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry( | 162 +Output_data_plt_arm_short<big_endian>::do_fill_plt_entry( |
137 unsigned char* pov, | 163 unsigned char* pov, |
138 Arm_address got_address, | 164 Arm_address got_address, |
139 Arm_address plt_address, | 165 Arm_address plt_address, |
140 @@ -7461,8 +7482,9 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entr
y( | 166 @@ -7794,8 +7816,9 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_entr
y( |
141 { | 167 { |
142 int32_t offset = ((got_address + got_offset) | 168 int32_t offset = ((got_address + got_offset) |
143 - (plt_address + plt_offset + 8)); | 169 - (plt_address + plt_offset + 8)); |
144 + if (offset < 0 || offset > 0x0fffffff) | 170 + if (offset < 0 || offset > 0x0fffffff) |
145 + gold_error(_("PLT offset too large, try linking with --long-plt")); | 171 + gold_error(_("PLT offset too large, try linking with --long-plt")); |
146 | 172 |
147 - gold_assert(offset >= 0 && offset < 0x0fffffff); | 173 - gold_assert(offset >= 0 && offset < 0x0fffffff); |
148 uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff); | 174 uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff); |
149 elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); | 175 elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); |
150 uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff); | 176 uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff); |
151 @@ -7471,6 +7493,66 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_ent
ry( | 177 @@ -7804,6 +7827,68 @@ Output_data_plt_arm_standard<big_endian>::do_fill_plt_ent
ry( |
152 elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); | 178 elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); |
153 } | 179 } |
154 | 180 |
155 +// This class generates long (16-byte) entries, for arbitrary displacements. | 181 +// This class generates long (16-byte) entries, for arbitrary displacements. |
156 + | 182 + |
157 +template<bool big_endian> | 183 +template<bool big_endian> |
158 +class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian
> | 184 +class Output_data_plt_arm_long : public Output_data_plt_arm_standard<big_endian
> |
159 +{ | 185 +{ |
160 + public: | 186 + public: |
161 + Output_data_plt_arm_long(Layout* layout, | 187 + Output_data_plt_arm_long(Layout* layout, |
162 +» » » Output_data_space* got_plt) | 188 +» » » Arm_output_data_got<big_endian>* got, |
163 + : Output_data_plt_arm_standard<big_endian>(layout, got_plt) | 189 +» » » Output_data_space* got_plt, |
| 190 +» » » Output_data_space* got_irelative) |
| 191 + : Output_data_plt_arm_standard<big_endian>(layout, got, got_plt, got_irelat
ive) |
164 + { } | 192 + { } |
165 + | 193 + |
166 + protected: | 194 + protected: |
167 + // Return the size of a PLT entry. | 195 + // Return the size of a PLT entry. |
168 + virtual unsigned int | 196 + virtual unsigned int |
169 + do_get_plt_entry_size() const | 197 + do_get_plt_entry_size() const |
170 + { return sizeof(plt_entry); } | 198 + { return sizeof(plt_entry); } |
171 + | 199 + |
172 + virtual void | 200 + virtual void |
173 + do_fill_plt_entry(unsigned char* pov, | 201 + do_fill_plt_entry(unsigned char* pov, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 + uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff); | 237 + uint32_t plt_insn2 = plt_entry[2] | ((offset >> 12) & 0xff); |
210 + elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); | 238 + elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); |
211 + uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff); | 239 + uint32_t plt_insn3 = plt_entry[3] | (offset & 0xfff); |
212 + elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3); | 240 + elfcpp::Swap<32, big_endian>::writeval(pov + 12, plt_insn3); |
213 +} | 241 +} |
214 + | 242 + |
215 // Write out the PLT. This uses the hand-coded instructions above, | 243 // Write out the PLT. This uses the hand-coded instructions above, |
216 // and adjusts them as needed. This is all specified by the arm ELF | 244 // and adjusts them as needed. This is all specified by the arm ELF |
217 // Processor Supplement. | 245 // Processor Supplement. |
218 diff --git a/gold/options.h b/gold/options.h | 246 diff --git a/gold/options.h b/gold/options.h |
219 index cf3b705..5bd93b1e 100644 | 247 index ffc44e6..8b5159f 100644 |
220 --- a/gold/options.h | 248 --- a/gold/options.h |
221 +++ b/gold/options.h | 249 +++ b/gold/options.h |
222 @@ -826,6 +826,10 @@ class General_options | 250 @@ -834,6 +834,10 @@ class General_options |
223 "veneer"), | 251 "veneer"), |
224 NULL); | 252 NULL); |
225 | 253 |
226 + DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false, | 254 + DEFINE_bool(long_plt, options::TWO_DASHES, '\0', false, |
227 + N_("(ARM only) Generate long PLT entries"), | 255 + N_("(ARM only) Generate long PLT entries"), |
228 + N_("(ARM only) Do not generate long PLT entries")); | 256 + N_("(ARM only) Do not generate long PLT entries")); |
229 + | 257 + |
230 DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false, | 258 DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false, |
231 N_("Ignored"), NULL); | 259 N_("Ignored"), NULL); |
232 | 260 |
OLD | NEW |