chmod ct-ng to be executable in the build dir.
1 2002-08-03 Jakub Jelinek <jakub@redhat.com>
3 * config/tc-i386.c (output_insn): Save frag_now and frag_now_fix ()
4 at start of insn, pass it to output_disp and output_imm.
5 (output_disp): Added arguments. If _GLOBAL_OFFSET_TABLE_ is seen
6 in displacement for R_386_32 reloc, use R_386_GOTPC and compute
8 (output_imm): Added arguments. Compute properly addend for
10 (md_apply_fix3): Remove R_386_GOTPC handling.
11 * testsuite/gas/i386/gotpc.s: New.
12 * testsuite/gas/i386/gotpc.d: New.
13 * testsuite/gas/i386/i386.exp: Add gotpc test.
15 --- binutils/gas/config/tc-i386.c.jj 2002-07-18 11:35:39.000000000 +0200
16 +++ binutils/gas/config/tc-i386.c 2002-08-02 21:13:18.000000000 +0200
17 @@ -104,8 +104,10 @@ static void output_insn PARAMS ((void));
18 static void output_branch PARAMS ((void));
19 static void output_jump PARAMS ((void));
20 static void output_interseg_jump PARAMS ((void));
21 -static void output_imm PARAMS ((void));
22 -static void output_disp PARAMS ((void));
23 +static void output_imm PARAMS ((fragS *insn_start_frag,
24 + offsetT insn_start_off));
25 +static void output_disp PARAMS ((fragS *insn_start_frag,
26 + offsetT insn_start_off));
28 static void s_bss PARAMS ((int));
30 @@ -3101,14 +3103,21 @@ output_interseg_jump ()
31 md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
38 + fragS *insn_start_frag;
39 + offsetT insn_start_off;
41 /* Tie dwarf2 debug info to the address at the start of the insn.
42 We can't do this after the insn has been output as the current
43 frag may have been closed off. eg. by frag_var. */
46 + insn_start_frag = frag_now;
47 + insn_start_off = frag_now_fix ();
50 if (i.tm.opcode_modifier & Jump)
52 @@ -3179,10 +3188,10 @@ output_insn ()
57 + output_disp (insn_start_frag, insn_start_off);
61 + output_imm (insn_start_frag, insn_start_off);
65 @@ -3194,7 +3203,9 @@ output_insn ()
70 +output_disp (insn_start_frag, insn_start_off)
71 + fragS *insn_start_frag;
72 + offsetT insn_start_off;
76 @@ -3224,6 +3235,7 @@ output_disp ()
80 + RELOC_ENUM reloc_type;
83 int pcrel = (i.flags[n] & Operand_PCrel) != 0;
84 @@ -3266,16 +3278,50 @@ output_disp ()
88 + reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
90 + if (reloc_type == BFD_RELOC_32
92 + && GOT_symbol == i.op[n].disps->X_add_symbol
93 + && (i.op[n].disps->X_op == O_symbol
94 + || (i.op[n].disps->X_op == O_add
95 + && ((symbol_get_value_expression
96 + (i.op[n].disps->X_op_symbol)->X_op)
101 + if (insn_start_frag == frag_now)
102 + add = (p - frag_now->fr_literal) - insn_start_off;
107 + add = insn_start_frag->fr_fix - insn_start_off;
108 + for (fr = insn_start_frag->fr_next;
109 + fr && fr != frag_now; fr = fr->fr_next)
111 + add += p - frag_now->fr_literal;
114 + /* We don't support dynamic linking on x86-64 yet. */
115 + if (flag_code == CODE_64BIT)
117 + reloc_type = BFD_RELOC_386_GOTPC;
118 + i.op[n].disps->X_add_number += add;
121 fix_new_exp (frag_now, p - frag_now->fr_literal, size,
122 - i.op[n].disps, pcrel,
123 - reloc (size, pcrel, sign, i.reloc[n]));
124 + i.op[n].disps, pcrel, reloc_type);
132 +output_imm (insn_start_frag, insn_start_off)
133 + fragS *insn_start_frag;
134 + offsetT insn_start_off;
138 @@ -3328,6 +3374,48 @@ output_imm ()
139 p = frag_more (size);
140 reloc_type = reloc (size, 0, sign, i.reloc[n]);
142 + /* This is tough to explain. We end up with this one if we
143 + * have operands that look like
144 + * "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal here is to
145 + * obtain the absolute address of the GOT, and it is strongly
146 + * preferable from a performance point of view to avoid using
147 + * a runtime relocation for this. The actual sequence of
148 + * instructions often look something like:
153 + * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
155 + * The call and pop essentially return the absolute address
156 + * of the label .L66 and store it in %ebx. The linker itself
157 + * will ultimately change the first operand of the addl so
158 + * that %ebx points to the GOT, but to keep things simple, the
159 + * .o file must have this operand set so that it generates not
160 + * the absolute address of .L66, but the absolute address of
161 + * itself. This allows the linker itself simply treat a GOTPC
162 + * relocation as asking for a pcrel offset to the GOT to be
163 + * added in, and the addend of the relocation is stored in the
164 + * operand field for the instruction itself.
166 + * Our job here is to fix the operand so that it would add
167 + * the correct offset so that %ebx would point to itself. The
168 + * thing that is tricky is that .-.L66 will point to the
169 + * beginning of the instruction, so we need to further modify
170 + * the operand so that it will point to itself. There are
171 + * other cases where you have something like:
173 + * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66]
175 + * and here no correction would be required. Internally in
176 + * the assembler we treat operands of this form as not being
177 + * pcrel since the '.' is explicitly mentioned, and I wonder
178 + * whether it would simplify matters to do it this way. Who
179 + * knows. In earlier versions of the PIC patches, the
180 + * pcrel_adjust field was used to store the correction, but
181 + * since the expression is not pcrel, I felt it would be
182 + * confusing to do it this way. */
184 if (reloc_type == BFD_RELOC_32
186 && GOT_symbol == i.op[n].imms->X_add_symbol
187 @@ -3337,11 +3425,26 @@ output_imm ()
188 (i.op[n].imms->X_op_symbol)->X_op)
193 + if (insn_start_frag == frag_now)
194 + add = (p - frag_now->fr_literal) - insn_start_off;
199 + add = insn_start_frag->fr_fix - insn_start_off;
200 + for (fr = insn_start_frag->fr_next;
201 + fr && fr != frag_now; fr = fr->fr_next)
203 + add += p - frag_now->fr_literal;
206 /* We don't support dynamic linking on x86-64 yet. */
207 if (flag_code == CODE_64BIT)
209 reloc_type = BFD_RELOC_386_GOTPC;
210 - i.op[n].imms->X_add_number += 3;
211 + i.op[n].imms->X_add_number += add;
214 fix_new_exp (frag_now, p - frag_now->fr_literal, size,
215 @@ -4542,48 +4645,6 @@ md_apply_fix3 (fixP, valP, seg)
216 runtime we merely add the offset to the actual PLT entry. */
219 - case BFD_RELOC_386_GOTPC:
221 -/* This is tough to explain. We end up with this one if we have
222 - * operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal
223 - * here is to obtain the absolute address of the GOT, and it is strongly
224 - * preferable from a performance point of view to avoid using a runtime
225 - * relocation for this. The actual sequence of instructions often look
231 - * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
233 - * The call and pop essentially return the absolute address of
234 - * the label .L66 and store it in %ebx. The linker itself will
235 - * ultimately change the first operand of the addl so that %ebx points to
236 - * the GOT, but to keep things simple, the .o file must have this operand
237 - * set so that it generates not the absolute address of .L66, but the
238 - * absolute address of itself. This allows the linker itself simply
239 - * treat a GOTPC relocation as asking for a pcrel offset to the GOT to be
240 - * added in, and the addend of the relocation is stored in the operand
241 - * field for the instruction itself.
243 - * Our job here is to fix the operand so that it would add the correct
244 - * offset so that %ebx would point to itself. The thing that is tricky is
245 - * that .-.L66 will point to the beginning of the instruction, so we need
246 - * to further modify the operand so that it will point to itself.
247 - * There are other cases where you have something like:
249 - * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66]
251 - * and here no correction would be required. Internally in the assembler
252 - * we treat operands of this form as not being pcrel since the '.' is
253 - * explicitly mentioned, and I wonder whether it would simplify matters
254 - * to do it this way. Who knows. In earlier versions of the PIC patches,
255 - * the pcrel_adjust field was used to store the correction, but since the
256 - * expression is not pcrel, I felt it would be confusing to do it this
261 case BFD_RELOC_386_GOT32:
262 case BFD_RELOC_386_TLS_GD:
263 case BFD_RELOC_386_TLS_LDM:
264 --- binutils/gas/testsuite/gas/i386/gotpc.s.jj 2002-08-02 21:17:57.000000000 +0200
265 +++ binutils/gas/testsuite/gas/i386/gotpc.s 2002-08-03 22:55:47.000000000 +0200
269 + addl $_GLOBAL_OFFSET_TABLE_+[.-test], %eax
270 + addl $_GLOBAL_OFFSET_TABLE_+[.-test], %ebx
271 + addl $_GLOBAL_OFFSET_TABLE_, %eax
272 + addl $_GLOBAL_OFFSET_TABLE_, %ebx
273 + leal _GLOBAL_OFFSET_TABLE+[.-test](%eax), %ebx
274 + leal _GLOBAL_OFFSET_TABLE+[.-test](%ebx), %eax
275 + leal _GLOBAL_OFFSET_TABLE+[.-test](%eax), %eax
276 + leal _GLOBAL_OFFSET_TABLE+[.-test](%ebx), %ebx
277 + subl $_GLOBAL_OFFSET_TABLE_+[.-test], %eax
278 + subl $_GLOBAL_OFFSET_TABLE_+[.-test], %ebx
279 + subl $_GLOBAL_OFFSET_TABLE_, %eax
280 + subl $_GLOBAL_OFFSET_TABLE_, %ebx
281 + orl $_GLOBAL_OFFSET_TABLE_+[.-test], %eax
282 + orl $_GLOBAL_OFFSET_TABLE_+[.-test], %ebx
283 + orl $_GLOBAL_OFFSET_TABLE_, %eax
284 + orl $_GLOBAL_OFFSET_TABLE_, %ebx
285 + movl $_GLOBAL_OFFSET_TABLE_+[.-test], %eax
286 + movl $_GLOBAL_OFFSET_TABLE_+[.-test], %ebx
287 + movl $_GLOBAL_OFFSET_TABLE_, %eax
288 + movl $_GLOBAL_OFFSET_TABLE_, %ebx
289 + movl $_GLOBAL_OFFSET_TABLE_+[.-test], foo
290 + movl $_GLOBAL_OFFSET_TABLE_+[.-test], %gs:foo
291 + gs; movl $_GLOBAL_OFFSET_TABLE_+[.-test], foo
292 + movl $_GLOBAL_OFFSET_TABLE_+[.-test], _GLOBAL_OFFSET_TABLE_
293 + movl _GLOBAL_OFFSET_TABLE_+[.-test], %eax
294 + movl _GLOBAL_OFFSET_TABLE_+[.-test], %ebx
295 + movl %eax, _GLOBAL_OFFSET_TABLE_+[.-test]
296 + movl %ebx, _GLOBAL_OFFSET_TABLE_+[.-test]
297 + movl %eax, %gs:_GLOBAL_OFFSET_TABLE_+[.-test]
298 + movl %ebx, %gs:_GLOBAL_OFFSET_TABLE_+[.-test]
299 + gs; movl %eax, _GLOBAL_OFFSET_TABLE_+[.-test]
300 + gs; movl %ebx, _GLOBAL_OFFSET_TABLE_+[.-test]
301 + leal _GLOBAL_OFFSET_TABLE_@GOTOFF(%ebx), %eax
302 + leal _GLOBAL_OFFSET_TABLE_@GOTOFF(%ebx), %ebx
303 + movl _GLOBAL_OFFSET_TABLE_@GOTOFF(%ebx), %eax
304 + movl _GLOBAL_OFFSET_TABLE_@GOTOFF(%ebx), %ebx
305 + .long _GLOBAL_OFFSET_TABLE_+[.-test]
306 + .long _GLOBAL_OFFSET_TABLE_@GOTOFF
307 --- binutils/gas/testsuite/gas/i386/gotpc.d.jj 2002-08-02 21:18:43.000000000 +0200
308 +++ binutils/gas/testsuite/gas/i386/gotpc.d 2002-08-03 23:05:43.000000000 +0200
315 +Disassembly of section .text:
318 + 0: 05 01 00 00 00 [ ]*add \$0x1,%eax 1: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
319 + 5: 81 c3 07 00 00 00 [ ]*add \$0x7,%ebx 7: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
320 + b: 05 01 00 00 00 [ ]*add \$0x1,%eax c: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
321 + 10: 81 c3 02 00 00 00 [ ]*add \$0x2,%ebx 12: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
322 + 16: 8d 98 16 00 00 00 [ ]*lea 0x16\(%eax\),%ebx 18: (R_386_)?(dir)?32 _GLOBAL_OFFSET_TABLE
323 + 1c: 8d 83 1c 00 00 00 [ ]*lea 0x1c\(%ebx\),%eax 1e: (R_386_)?(dir)?32 _GLOBAL_OFFSET_TABLE
324 + 22: 8d 80 22 00 00 00 [ ]*lea 0x22\(%eax\),%eax 24: (R_386_)?(dir)?32 _GLOBAL_OFFSET_TABLE
325 + 28: 8d 9b 28 00 00 00 [ ]*lea 0x28\(%ebx\),%ebx 2a: (R_386_)?(dir)?32 _GLOBAL_OFFSET_TABLE
326 + 2e: 2d 2f 00 00 00 [ ]*sub \$0x2f,%eax 2f: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
327 + 33: 81 eb 35 00 00 00 [ ]*sub \$0x35,%ebx 35: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
328 + 39: 2d 01 00 00 00 [ ]*sub \$0x1,%eax 3a: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
329 + 3e: 81 eb 02 00 00 00 [ ]*sub \$0x2,%ebx 40: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
330 + 44: 0d 45 00 00 00 [ ]*or \$0x45,%eax 45: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
331 + 49: 81 cb 4b 00 00 00 [ ]*or \$0x4b,%ebx 4b: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
332 + 4f: 0d 01 00 00 00 [ ]*or \$0x1,%eax 50: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
333 + 54: 81 cb 02 00 00 00 [ ]*or \$0x2,%ebx 56: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
334 + 5a: b8 5b 00 00 00 [ ]*mov \$0x5b,%eax 5b: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
335 + 5f: bb 60 00 00 00 [ ]*mov \$0x60,%ebx 60: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
336 + 64: b8 01 00 00 00 [ ]*mov \$0x1,%eax 65: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
337 + 69: bb 01 00 00 00 [ ]*mov \$0x1,%ebx 6a: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
338 + 6e: c7 05 00 00 00 00 74 00 00 00 [ ]*movl \$0x74,0x0 70: (R_386_)?(dir)?32 foo
339 +[ ]*74: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
340 + 78: 65 c7 05 00 00 00 00 7f 00 00 00 [ ]*movl \$0x7f,%gs:0x0 7b: (R_386_)?(dir)?32 foo
341 +[ ]*7f: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
342 + 83: 65 c7 05 00 00 00 00 8a 00 00 00 [ ]*movl \$0x8a,%gs:0x0 86: (R_386_)?(dir)?32 foo
343 +[ ]*8a: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
344 + 8e: c7 05 02 00 00 00 94 00 00 00 [ ]*movl \$0x94,0x2 90: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
345 +[ ]*94: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
346 + 98: a1 99 00 00 00 [ ]*mov 0x99,%eax 99: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
347 + 9d: 8b 1d 9f 00 00 00 [ ]*mov 0x9f,%ebx 9f: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
348 + a3: a3 a4 00 00 00 [ ]*mov %eax,0xa4 a4: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
349 + a8: 89 1d aa 00 00 00 [ ]*mov %ebx,0xaa aa: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
350 + ae: 65 a3 b0 00 00 00 [ ]*mov %eax,%gs:0xb0 b0: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
351 + b4: 65 89 1d b7 00 00 00 [ ]*mov %ebx,%gs:0xb7 b7: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
352 + bb: 65 a3 bd 00 00 00 [ ]*mov %eax,%gs:0xbd bd: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
353 + c1: 65 89 1d c4 00 00 00 [ ]*mov %ebx,%gs:0xc4 c4: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
354 + c8: 8d 83 00 00 00 00 [ ]*lea 0x0\(%ebx\),%eax ca: (R_386_)?GOTOFF _GLOBAL_OFFSET_TABLE_
355 + ce: 8d 9b 00 00 00 00 [ ]*lea 0x0\(%ebx\),%ebx d0: (R_386_)?GOTOFF _GLOBAL_OFFSET_TABLE_
356 + d4: 8b 83 00 00 00 00 [ ]*mov 0x0\(%ebx\),%eax d6: (R_386_)?GOTOFF _GLOBAL_OFFSET_TABLE_
357 + da: 8b 9b 00 00 00 00 [ ]*mov 0x0\(%ebx\),%ebx dc: (R_386_)?GOTOFF _GLOBAL_OFFSET_TABLE_
358 + e0: e0 00 [ ]*loopne e2 <test\+0xe2> e0: (R_386_)?GOTPC _GLOBAL_OFFSET_TABLE_
359 + e2: 00 00 [ ]*add %al,\(%eax\)
360 + e4: 00 00 [ ]*add %al,\(%eax\) e4: (R_386_)?GOTOFF _GLOBAL_OFFSET_TABLE_
362 --- binutils/gas/testsuite/gas/i386/i386.exp.jj 2002-07-18 11:35:39.000000000 +0200
363 +++ binutils/gas/testsuite/gas/i386/i386.exp 2002-08-02 21:57:46.000000000 +0200
364 @@ -53,6 +53,7 @@ if [expr ([istarget "i*86-*-*"] || [ist
366 run_dump_test "ssemmx2"
368 + run_dump_test "gotpc"
370 # PIC is only supported on ELF targets.
371 if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"] )