[8/8] x86: correct overflow checking for 16-bit PC-relative relocs

Message ID 7b325207-3e09-720c-2a8e-a1a6e14a2938@suse.com
State New
Headers show
Series
  • x86: assorted relocation handling related adjustments (part II)
Related show

Commit Message

Nick Clifton via Binutils April 23, 2021, 8:38 a.m.
The only insn requiring a truly 16-bit PC-relative relocation outside of
16-bit mode is XBEGIN (with an operand size override). For it, the
relocation generated should behave similar to 8- and (for 64-bit) 32-bit
PC-relatives ones, i.e. be checked for a signed value to fit the field.
This same mode is also correct for 16-bit code. Outside of 16-bit code,
branches with operand size overrides act in a truly PC-relative way only
when living in the low 32k of address space, as they truncate rIP to 16
bits. This can't be expressed by a PC-relative relocation.

Putting in place a new testcase, I'd like to note that the two existing
ones (pcrel16 and pcrel16abs) appear to be pretty pointless: They don't
expect any error despite supposedly checking for overflow, and in fact
there can't possibly be any error for the
- former since gas doesn't emit any relocation in the first place there,
- latter because the way the relocation gets expressed by gas doesn't
  allow the linker to notice the overflow; it should be detected by gas
  if at all, but see above (an error would be reported here for x86-64
  afaict, but this test doesn't get re-used there).

bfd/
2021-04-XX  Jan Beulich  <jbeulich@suse.com>

	* elf32-i386.c (elf_howto_table): Switch R_386_PC16 to
	complain_overflow_signed.
	* elf64-x86-64.c (x86_64_elf_howto_table): Switch R_X86_64_PC16
	to complain_overflow_signed.

ld/
2021-04-XX  Jan Beulich  <jbeulich@suse.com>

	* testsuite/ld-i386/pcrel16-2.s, testsuite/ld-i386/pcrel16-2.d,
	testsuite/ld-x86-64/pcrel16-2.d: New.
	* testsuite/ld-i386/i386.exp: Run new test.
	* testsuite/ld-x86-64/x86-64.exp: Likewise.

Comments

Nick Clifton via Binutils April 23, 2021, 1:36 p.m. | #1
On Fri, Apr 23, 2021 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> The only insn requiring a truly 16-bit PC-relative relocation outside of

> 16-bit mode is XBEGIN (with an operand size override). For it, the

> relocation generated should behave similar to 8- and (for 64-bit) 32-bit

> PC-relatives ones, i.e. be checked for a signed value to fit the field.

> This same mode is also correct for 16-bit code. Outside of 16-bit code,

> branches with operand size overrides act in a truly PC-relative way only

> when living in the low 32k of address space, as they truncate rIP to 16

> bits. This can't be expressed by a PC-relative relocation.

>

> Putting in place a new testcase, I'd like to note that the two existing

> ones (pcrel16 and pcrel16abs) appear to be pretty pointless: They don't

> expect any error despite supposedly checking for overflow, and in fact

> there can't possibly be any error for the

> - former since gas doesn't emit any relocation in the first place there,

> - latter because the way the relocation gets expressed by gas doesn't

>   allow the linker to notice the overflow; it should be detected by gas

>   if at all, but see above (an error would be reported here for x86-64

>   afaict, but this test doesn't get re-used there).

>

> bfd/

> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * elf32-i386.c (elf_howto_table): Switch R_386_PC16 to

>         complain_overflow_signed.

>         * elf64-x86-64.c (x86_64_elf_howto_table): Switch R_X86_64_PC16

>         to complain_overflow_signed.

>

> ld/

> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * testsuite/ld-i386/pcrel16-2.s, testsuite/ld-i386/pcrel16-2.d,

>         testsuite/ld-x86-64/pcrel16-2.d: New.

>         * testsuite/ld-i386/i386.exp: Run new test.

>         * testsuite/ld-x86-64/x86-64.exp: Likewise.

>

> --- a/bfd/elf32-i386.c

> +++ b/bfd/elf32-i386.c

> @@ -93,7 +93,7 @@ static reloc_howto_type elf_howto_table[

>    HOWTO(R_386_16, 0, 1, 16, false, 0, complain_overflow_bitfield,

>         bfd_elf_generic_reloc, "R_386_16",

>         true, 0xffff, 0xffff, false),

> -  HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_bitfield,

> +  HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_signed,

>         bfd_elf_generic_reloc, "R_386_PC16",

>         true, 0xffff, 0xffff, true),

>    HOWTO(R_386_8, 0, 0, 8, false, 0, complain_overflow_bitfield,

> --- a/bfd/elf64-x86-64.c

> +++ b/bfd/elf64-x86-64.c

> @@ -82,7 +82,7 @@ static reloc_howto_type x86_64_elf_howto

>         false),

>    HOWTO(R_X86_64_16, 0, 1, 16, false, 0, complain_overflow_bitfield,

>         bfd_elf_generic_reloc, "R_X86_64_16", false, 0xffff, 0xffff, false),

> -  HOWTO(R_X86_64_PC16,0, 1, 16, true, 0, complain_overflow_bitfield,

> +  HOWTO(R_X86_64_PC16, 0, 1, 16, true, 0, complain_overflow_signed,

>         bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0xffff, 0xffff, true),

>    HOWTO(R_X86_64_8, 0, 0, 8, false, 0, complain_overflow_bitfield,

>         bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false),

> --- a/ld/testsuite/ld-i386/i386.exp

> +++ b/ld/testsuite/ld-i386/i386.exp

> @@ -297,6 +297,7 @@ run_dump_test "abs"

>  run_dump_test "pcrel8"

>  run_dump_test "pcrel16"

>  run_dump_test "pcrel16abs"

> +run_dump_test "pcrel16-2"

>  run_dump_test "alloc"

>  run_dump_test "warn1"

>  run_dump_test "tlsgd2"

> --- /dev/null

> +++ b/ld/testsuite/ld-i386/pcrel16-2.d

> @@ -0,0 +1,5 @@

> +#name: PCREL16 overflow (2)

> +#as: --32

> +#ld: -melf_i386

> +#error: .*relocation truncated to fit: R_386_PC16 .*t16.*

> +#error: .*relocation truncated to fit: R_386_PC16 .*_start.*

> --- /dev/null

> +++ b/ld/testsuite/ld-i386/pcrel16-2.s

> @@ -0,0 +1,12 @@

> +       .text

> +       .global _start

> +_start:

> +       data16 xbegin t16

> +       ret

> +

> +       .fill 0x8000,1,0xcc

> +

> +       .global t16

> +t16:

> +       data16 xbegin _start

> +       ret

> --- /dev/null

> +++ b/ld/testsuite/ld-x86-64/pcrel16-2.d

> @@ -0,0 +1,5 @@

> +#name: PCREL16 overflow (2)

> +#source: ../ld-i386/pcrel16-2.s

> +#ld:

> +#error: .*relocation truncated to fit: R_X86_64_PC16 .*t16.*

> +#error: .*relocation truncated to fit: R_X86_64_PC16 .*_start.*

> --- a/ld/testsuite/ld-x86-64/x86-64.exp

> +++ b/ld/testsuite/ld-x86-64/x86-64.exp

> @@ -261,6 +261,7 @@ run_dump_test "abs-l1om"

>  run_dump_test "apic"

>  run_dump_test "pcrel8"

>  run_dump_test "pcrel16"

> +run_dump_test "pcrel16-2"

>  run_dump_test "tlsgd2"

>  run_dump_test "tlsgd3"

>  run_dump_test "tlsgd12"

>


OK.

Thanks.

-- 
H.J.

Patch

--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -93,7 +93,7 @@  static reloc_howto_type elf_howto_table[
   HOWTO(R_386_16, 0, 1, 16, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_386_16",
 	true, 0xffff, 0xffff, false),
-  HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_bitfield,
+  HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_386_PC16",
 	true, 0xffff, 0xffff, true),
   HOWTO(R_386_8, 0, 0, 8, false, 0, complain_overflow_bitfield,
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -82,7 +82,7 @@  static reloc_howto_type x86_64_elf_howto
 	false),
   HOWTO(R_X86_64_16, 0, 1, 16, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_X86_64_16", false, 0xffff, 0xffff, false),
-  HOWTO(R_X86_64_PC16,0, 1, 16, true, 0, complain_overflow_bitfield,
+  HOWTO(R_X86_64_PC16, 0, 1, 16, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0xffff, 0xffff, true),
   HOWTO(R_X86_64_8, 0, 0, 8, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false),
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -297,6 +297,7 @@  run_dump_test "abs"
 run_dump_test "pcrel8"
 run_dump_test "pcrel16"
 run_dump_test "pcrel16abs"
+run_dump_test "pcrel16-2"
 run_dump_test "alloc"
 run_dump_test "warn1"
 run_dump_test "tlsgd2"
--- /dev/null
+++ b/ld/testsuite/ld-i386/pcrel16-2.d
@@ -0,0 +1,5 @@ 
+#name: PCREL16 overflow (2)
+#as: --32
+#ld: -melf_i386
+#error: .*relocation truncated to fit: R_386_PC16 .*t16.*
+#error: .*relocation truncated to fit: R_386_PC16 .*_start.*
--- /dev/null
+++ b/ld/testsuite/ld-i386/pcrel16-2.s
@@ -0,0 +1,12 @@ 
+	.text
+	.global _start
+_start:
+	data16 xbegin t16
+	ret
+
+	.fill 0x8000,1,0xcc
+
+	.global t16
+t16:
+	data16 xbegin _start
+	ret
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pcrel16-2.d
@@ -0,0 +1,5 @@ 
+#name: PCREL16 overflow (2)
+#source: ../ld-i386/pcrel16-2.s
+#ld:
+#error: .*relocation truncated to fit: R_X86_64_PC16 .*t16.*
+#error: .*relocation truncated to fit: R_X86_64_PC16 .*_start.*
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -261,6 +261,7 @@  run_dump_test "abs-l1om"
 run_dump_test "apic"
 run_dump_test "pcrel8"
 run_dump_test "pcrel16"
+run_dump_test "pcrel16-2"
 run_dump_test "tlsgd2"
 run_dump_test "tlsgd3"
 run_dump_test "tlsgd12"