From b9519cfe9828b9ee5a73e74b4be83d46f33e6886 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 19 Dec 2018 12:21:56 -0800 Subject: [PATCH] x86: Properly handle PLT expression in directive For PLT expressions, we should subtract the PLT relocation size only for jump instructions. Since PLT relocations are PC relative, we only allow "symbol@PLT" in PLT expression. gas/ PR gas/23997 * config/tc-i386.c (x86_cons): Check for invalid PLT expression. (md_apply_fix): Subtract the PLT relocation size only for jump instructions. * testsuite/gas/i386/reloc32.s: Add test for invalid PLT expression. * testsuite/gas/i386/reloc64.s: Likewise. * testsuite/gas/i386/ilp32/reloc64.s: Likewise. * testsuite/gas/i386/reloc32.l: Updated. * testsuite/gas/i386/reloc64.l: Likewise. * testsuite/gas/i386/ilp32/reloc64.l: Likewise. ld/ PR gas/23997 * testsuite/ld-i386/i386.exp: Run PR gas/23997 test. * testsuite/ld-x86-64/x86-64.exp: Likewise. * testsuite/ld-x86-64/pr23997a.s: New file. * testsuite/ld-x86-64/pr23997b.c: Likewise. * testsuite/ld-x86-64/pr23997c.c: Likewise. --- gas/ChangeLog | 14 ++++++++++++++ gas/config/tc-i386.c | 17 ++++++++++++++--- gas/testsuite/gas/i386/ilp32/reloc64.l | 1 + gas/testsuite/gas/i386/ilp32/reloc64.s | 1 + gas/testsuite/gas/i386/reloc32.l | 1 + gas/testsuite/gas/i386/reloc32.s | 1 + gas/testsuite/gas/i386/reloc64.l | 1 + gas/testsuite/gas/i386/reloc64.s | 1 + ld/ChangeLog | 9 +++++++++ ld/testsuite/ld-i386/i386.exp | 9 +++++++++ ld/testsuite/ld-x86-64/pr23997a.s | 6 ++++++ ld/testsuite/ld-x86-64/pr23997b.c | 25 +++++++++++++++++++++++++ ld/testsuite/ld-x86-64/pr23997c.c | 7 +++++++ ld/testsuite/ld-x86-64/x86-64.exp | 8 ++++++++ 14 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pr23997a.s create mode 100644 ld/testsuite/ld-x86-64/pr23997b.c create mode 100644 ld/testsuite/ld-x86-64/pr23997c.c diff --git a/gas/ChangeLog b/gas/ChangeLog index 00159202d1..b21680a158 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2018-12-19 H.J. Lu + + PR gas/23997 + * config/tc-i386.c (x86_cons): Check for invalid PLT expression. + (md_apply_fix): Subtract the PLT relocation size only for jump + instructions. + * testsuite/gas/i386/reloc32.s: Add test for invalid PLT + expression. + * testsuite/gas/i386/reloc64.s: Likewise. + * testsuite/gas/i386/ilp32/reloc64.s: Likewise. + * testsuite/gas/i386/reloc32.l: Updated. + * testsuite/gas/i386/reloc64.l: Likewise. + * testsuite/gas/i386/ilp32/reloc64.l: Likewise. + 2018-12-14 H.J. Lu PR ld/23900 diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8e25e6c7a0..764063119d 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -8919,6 +8919,15 @@ x86_cons (expressionS *exp, int size) as_bad (_("missing or invalid expression `%s'"), save); *input_line_pointer = c; } + else if ((got_reloc == BFD_RELOC_386_PLT32 + || got_reloc == BFD_RELOC_X86_64_PLT32) + && exp->X_op != O_symbol) + { + char c = *input_line_pointer; + *input_line_pointer = 0; + as_bad (_("invalid PLT expression `%s'"), save); + *input_line_pointer = c; + } } } else @@ -10533,9 +10542,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { case BFD_RELOC_386_PLT32: case BFD_RELOC_X86_64_PLT32: - /* Make the jump instruction point to the address of the operand. At - runtime we merely add the offset to the actual PLT entry. */ - value = -4; + /* Make the jump instruction point to the address of the operand. + At runtime we merely add the offset to the actual PLT entry. + NB: Subtract the offset size only for jump instructions. */ + if (fixP->fx_pcrel) + value = -4; break; case BFD_RELOC_386_TLS_GD: diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.l b/gas/testsuite/gas/i386/ilp32/reloc64.l index ff49194597..7a1808e4e9 100644 --- a/gas/testsuite/gas/i386/ilp32/reloc64.l +++ b/gas/testsuite/gas/i386/ilp32/reloc64.l @@ -51,3 +51,4 @@ .*:175: Error: .* .*:176: Error: .* .*:177: Error: .* +.*:189: Error: .* diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.s b/gas/testsuite/gas/i386/ilp32/reloc64.s index 77764b3c62..3ab25eff6c 100644 --- a/gas/testsuite/gas/i386/ilp32/reloc64.s +++ b/gas/testsuite/gas/i386/ilp32/reloc64.s @@ -186,3 +186,4 @@ bad .byte xtrn@tpoff .quad xtrn - 0x80000000 .long xtrn@got - 4 .long xtrn@got + 4 +bad .long xtrn@plt - . diff --git a/gas/testsuite/gas/i386/reloc32.l b/gas/testsuite/gas/i386/reloc32.l index 9299445851..3fb3255fc8 100644 --- a/gas/testsuite/gas/i386/reloc32.l +++ b/gas/testsuite/gas/i386/reloc32.l @@ -65,4 +65,5 @@ .*:159: Error: .* .*:160: Error: .* .*:161: Error: .* +.*:164: Error: .* #pass diff --git a/gas/testsuite/gas/i386/reloc32.s b/gas/testsuite/gas/i386/reloc32.s index 855dcf578d..e766a3dcc2 100644 --- a/gas/testsuite/gas/i386/reloc32.s +++ b/gas/testsuite/gas/i386/reloc32.s @@ -161,3 +161,4 @@ bad .byte xtrn@ntpoff bad .byte xtrn@tpoff .long xtrn@got + 4 .long xtrn@got - 4 +bad .long xtrn@plt - . diff --git a/gas/testsuite/gas/i386/reloc64.l b/gas/testsuite/gas/i386/reloc64.l index 5e970cb7b6..6d7a3c70c4 100644 --- a/gas/testsuite/gas/i386/reloc64.l +++ b/gas/testsuite/gas/i386/reloc64.l @@ -81,3 +81,4 @@ .*:218: Error: .* .*:219: Error: .* .*:220: Error: .* +.*:227: Error: .* diff --git a/gas/testsuite/gas/i386/reloc64.s b/gas/testsuite/gas/i386/reloc64.s index 0f9c51e4c8..bc6f0fa6cc 100644 --- a/gas/testsuite/gas/i386/reloc64.s +++ b/gas/testsuite/gas/i386/reloc64.s @@ -224,3 +224,4 @@ bad .byte xtrn@gotplt mov xtrn(,%ebx), %eax vgatherdps %xmm2, xtrn(,%xmm1), %xmm0 addr32 vgatherdps %xmm2, xtrn(,%xmm1), %xmm0 +bad .long xtrn@plt - . diff --git a/ld/ChangeLog b/ld/ChangeLog index 17a2e453ab..c7d4a0c543 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2018-12-19 H.J. Lu + + PR gas/23997 + * testsuite/ld-i386/i386.exp: Run PR gas/23997 test. + * testsuite/ld-x86-64/x86-64.exp: Likewise. + * testsuite/ld-x86-64/pr23997a.s: New file. + * testsuite/ld-x86-64/pr23997b.c: Likewise. + * testsuite/ld-x86-64/pr23997c.c: Likewise. + 2018-12-19 H.J. Lu * testsuite/ld-x86-64/x86-64.exp: Rename PR ld/22842 run-time diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index f86a54d27a..b3c489a85d 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -1420,6 +1420,15 @@ if { [isnative] "pr22842" \ "pass.out" \ ] \ + [list \ + "Run pr23997" \ + "" \ + "" \ + { ../ld-x86-64/pr23997a.s ../ld-x86-64/pr23997b.c \ + ../ld-x86-64/pr23997c.c } \ + "pr23997" \ + "pass.out" \ + ] \ ] if { [at_least_gcc_version 5 0] } { diff --git a/ld/testsuite/ld-x86-64/pr23997a.s b/ld/testsuite/ld-x86-64/pr23997a.s new file mode 100644 index 0000000000..8d72c626a3 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr23997a.s @@ -0,0 +1,6 @@ + .text + .p2align 3 + .globl foo_p +foo_p: + .long foo@plt + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/pr23997b.c b/ld/testsuite/ld-x86-64/pr23997b.c new file mode 100644 index 0000000000..02cb8f8f7f --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr23997b.c @@ -0,0 +1,25 @@ +#include + +typedef void (*func_t) (void); + +extern func_t get_foo (void); + +void +foo (void) +{ +} + +int +main () +{ + func_t p; + + foo (); + p = get_foo (); + p (); + + if (foo == p) + printf ("PASS\n"); + + return 0; +} diff --git a/ld/testsuite/ld-x86-64/pr23997c.c b/ld/testsuite/ld-x86-64/pr23997c.c new file mode 100644 index 0000000000..357315751d --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr23997c.c @@ -0,0 +1,7 @@ +extern int foo_p; + +void * +get_foo (void) +{ + return (void *) ((long) &foo_p + foo_p); +} diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 75e2546c0c..c9e8ecbb19 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -1594,6 +1594,14 @@ if { [isnative] && [which $CC] != 0 } { "pr22842" \ "pass.out" \ ] \ + [list \ + "Run pr23997" \ + "" \ + "" \ + { pr23997a.s pr23997b.c pr23997c.c } \ + "pr23997" \ + "pass.out" \ + ] \ ] # Run-time tests which require working ifunc attribute support.