x86: correct overflow checking for 16-bit PC-relative relocs
authorJan Beulich <jbeulich@suse.com>
Mon, 26 Apr 2021 08:41:35 +0000 (10:41 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 26 Apr 2021 08:41:35 +0000 (10:41 +0200)
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/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pcrel16-2.d [new file with mode: 0644]
ld/testsuite/ld-i386/pcrel16-2.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pcrel16-2.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 701357c3ad7d8c3f416d7d1158bcf26c4253b97f..45397ef04b9a4f60ffee17ffb7af4102819db050 100644 (file)
@@ -1,3 +1,10 @@
+2021-04-26  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.
+
 2021-04-23  Eric Botcazou  <ebotcazou@adacore.com>
 
        * elf.c (special_sections_p): Add .persistent.bss.
index dee5352a0b605e9c5326e1c87243531cb6951e69..ffe764422fffc810c4c9c3665873a8b14ed20193 100644 (file)
@@ -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,
index 1204b29e396d5388a6ddd021d27095cde6dd666a..840555c2000aadf63e428210a577c8db7c04e13d 100644 (file)
@@ -82,7 +82,7 @@ static reloc_howto_type x86_64_elf_howto_table[] =
        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),
index b736aa805debbb1737a419044237aa895692c502..9bb178e42485aeef2d80e17580f2daac57be6e22 100644 (file)
@@ -1,3 +1,10 @@
+2021-04-26  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.
+
 2021-04-23  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/27771
index 6ad69a818f5ebed7522c1feac7ca3ee22312d23a..d0b3f69fb8d2baa27931c690bcc930856e9fc394 100644 (file)
@@ -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"
diff --git a/ld/testsuite/ld-i386/pcrel16-2.d b/ld/testsuite/ld-i386/pcrel16-2.d
new file mode 100644 (file)
index 0000000..c1c340f
--- /dev/null
@@ -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.*
diff --git a/ld/testsuite/ld-i386/pcrel16-2.s b/ld/testsuite/ld-i386/pcrel16-2.s
new file mode 100644 (file)
index 0000000..2e97417
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .global _start
+_start:
+       data16 xbegin t16
+       ret
+
+       .fill 0x8000,1,0xcc
+
+       .global t16
+t16:
+       data16 xbegin _start
+       ret
diff --git a/ld/testsuite/ld-x86-64/pcrel16-2.d b/ld/testsuite/ld-x86-64/pcrel16-2.d
new file mode 100644 (file)
index 0000000..5346a5b
--- /dev/null
@@ -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.*
index 877d6ba5fa4b680a2235c31b2abbbb4b787a4f91..269f70d05b298a71133c558ce8f41409da9a5462 100644 (file)
@@ -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"