public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Jan Beulich <jbeulich@suse.com>
To: Binutils <binutils@sourceware.org>
Subject: [PATCH v2 1/3] x86-64/ELF: permit relaxed overflow checking for 32-bit PC-relative relocs
Date: Fri, 4 Mar 2022 14:34:58 +0100	[thread overview]
Message-ID: <319f39e5-1f17-23ef-e3fa-2169876aa31c@suse.com> (raw)
In-Reply-To: <af880e85-7b81-b9b5-e914-95ce9e317565@suse.com>

Right now it is impossible to encode certain valid 32-bit mode
constructs; see the respective new test case. Note that there are
further 32-bit PC-relative relocations, but I don't think they make a
lot of sense to use in mixed-bitness code, so they're not having
overrides put in place.

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).
---
TBD: I didn't put thoughts yet into also making this work when linking
     ELF to PE.

Note that I'm not sure at all whether this propagation of the struct
elf_linker_x86_params pointer is actually acceptable. But this is the
5th or 6th try I made, with all others having been worse or not even
working out. Hence I'd need pretty detailed guidance on how else the
information could be made available.
---
v2: Re-base and split.

--- a/bfd/elf-linker-x86.h
+++ b/bfd/elf-linker-x86.h
@@ -28,6 +28,13 @@ enum elf_x86_prop_report
   prop_report_shstk	= 1 << 3    /* Report missing SHSTK property.  */
 };
 
+/* Control of PC32 (on 64-bit) overflow check strictness.  */
+enum elf_x86_pcrel_relocs
+{
+  pcrel_relocs_default,
+  pcrel_relocs_lax,
+};
+
 /* Used to pass x86-specific linker options from ld to bfd.  */
 struct elf_linker_x86_params
 {
@@ -64,6 +71,9 @@ struct elf_linker_x86_params
   /* Report relative relocations.  */
   unsigned int report_relative_reloc : 1;
 
+  /* Strictness of PC32 (on 64-bit) overflow checks.  */
+  enum elf_x86_pcrel_relocs pcrel_relocs;
+
   /* X86-64 ISA level needed.  */
   unsigned int isa_level;
 
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -192,6 +192,15 @@ static reloc_howto_type x86_64_elf_howto
 	false)
 };
 
+static reloc_howto_type x86_64_howto_pc32_lax =
+  HOWTO(R_X86_64_PC32, 0, 2, 32, true, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0, 0xffffffff, true);
+
+static reloc_howto_type x86_64_howto_pc32_bnd_lax =
+  HOWTO(R_X86_64_PC32_BND, 0, 2, 32, true, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_PC32_BND", false, 0, 0xffffffff,
+	true);
+
 /* Map BFD relocs to the x86_64 elf relocs.  */
 struct elf_reloc_map
 {
@@ -248,6 +257,30 @@ static const struct elf_reloc_map x86_64
 };
 
 static reloc_howto_type *
+elf_x86_64_reloc_override (const bfd *abfd, reloc_howto_type *howto)
+{
+  const struct elf_linker_x86_params *params = elf_x86_tdata (abfd)->params;
+
+  switch (howto->type)
+    {
+    default:
+      break;
+
+    case R_X86_64_PC32:
+      if (params == NULL || params->pcrel_relocs != pcrel_relocs_lax)
+	break;
+      return &x86_64_howto_pc32_lax;
+
+    case R_X86_64_PC32_BND:
+      if (params == NULL || params->pcrel_relocs != pcrel_relocs_lax)
+	break;
+      return &x86_64_howto_pc32_bnd_lax;
+    }
+
+  return howto;
+}
+
+static reloc_howto_type *
 elf_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type)
 {
   unsigned i;
@@ -275,7 +308,7 @@ elf_x86_64_rtype_to_howto (bfd *abfd, un
   else
     i = r_type - (unsigned int) R_X86_64_vt_offset;
   BFD_ASSERT (x86_64_elf_howto_table[i].type == r_type);
-  return &x86_64_elf_howto_table[i];
+  return elf_x86_64_reloc_override (abfd, &x86_64_elf_howto_table[i]);
 }
 
 /* Given a BFD reloc type, return a HOWTO structure.  */
@@ -313,7 +346,7 @@ elf_x86_64_reloc_name_lookup (bfd *abfd,
   for (i = 0; i < ARRAY_SIZE (x86_64_elf_howto_table); i++)
     if (x86_64_elf_howto_table[i].name != NULL
 	&& strcasecmp (x86_64_elf_howto_table[i].name, r_name) == 0)
-      return &x86_64_elf_howto_table[i];
+      return elf_x86_64_reloc_override (abfd, &x86_64_elf_howto_table[i]);
 
   return NULL;
 }
@@ -1846,6 +1879,9 @@ elf_x86_64_scan_relocs (bfd *abfd, struc
 
   BFD_ASSERT (is_x86_elf (abfd, htab));
 
+  /* Make command line controlled settings accessible from the object.  */
+  elf_x86_tdata (abfd)->params = htab->params;
+
   /* Get the section contents.  */
   if (elf_section_data (sec)->this_hdr.contents != NULL)
     contents = elf_section_data (sec)->this_hdr.contents;
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -702,6 +702,9 @@ struct elf_x86_obj_tdata
   /* R_*_RELATIVE relocation in GOT for this local symbol has been
      processed.  */
   char *relative_reloc_done;
+
+  /* Container holding command line controlled linker settings.  */
+  const struct elf_linker_x86_params *params;
 };
 
 enum elf_x86_plt_type
--- /dev/null
+++ b/gas/testsuite/gas/i386/code32.d
@@ -0,0 +1,3 @@
+#name: x86-64 code32
+#as: -mx86-used-note=no --generate-missing-build-notes=no
+#readelf: -n
--- /dev/null
+++ b/gas/testsuite/gas/i386/code32.s
@@ -0,0 +1,11 @@
+	.code32
+	.text
+	.section .text.0, "ax", @progbits
+	.type func0, @function
+func0:
+	call func1
+	ret
+	.section .text.1, "ax", @progbits
+	.type func1, @function
+func1:
+	jmp func0
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1331,6 +1331,7 @@ if [gas_64_check] then {
 	run_dump_test "x86-64-property-8"
 	run_dump_test "x86-64-property-9"
 	run_dump_test "x86-64-property-14"
+	run_dump_test "code32"
 
 	if {[istarget "*-*-linux*"]} then {
 	    run_dump_test "x86-64-align-branch-3"
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -2,6 +2,7 @@ source_sh ${srcdir}/emulparams/plt_unwin
 source_sh ${srcdir}/emulparams/extern_protected_data.sh
 source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
 source_sh ${srcdir}/emulparams/reloc_overflow.sh
+source_sh ${srcdir}/emulparams/pcrel-relocs.sh
 source_sh ${srcdir}/emulparams/call_nop.sh
 source_sh ${srcdir}/emulparams/cet.sh
 source_sh ${srcdir}/emulparams/x86-report-relative.sh
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -2,6 +2,7 @@ source_sh ${srcdir}/emulparams/plt_unwin
 source_sh ${srcdir}/emulparams/extern_protected_data.sh
 source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
 source_sh ${srcdir}/emulparams/reloc_overflow.sh
+source_sh ${srcdir}/emulparams/pcrel-relocs.sh
 source_sh ${srcdir}/emulparams/call_nop.sh
 source_sh ${srcdir}/emulparams/cet.sh
 source_sh ${srcdir}/emulparams/x86-report-relative.sh
--- /dev/null
+++ b/ld/emulparams/pcrel-relocs.sh
@@ -0,0 +1,11 @@
+PARSE_AND_LIST_OPTIONS_STRICT_PCREL_RELOCS='
+  fprintf (file, _("\
+  -z lax-pcrel-relocs         Lax PC-relative relocation overflow checks\n"));
+'
+PARSE_AND_LIST_ARGS_CASE_Z_STRICT_PCREL_RELOCS='
+      else if (strcmp (optarg, "lax-pcrel-relocs") == 0)
+	params.pcrel_relocs = pcrel_relocs_lax;
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_STRICT_PCREL_RELOCS"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_STRICT_PCREL_RELOCS"
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1372,6 +1372,12 @@ missing properties in input files.  @opt
 the linker issue an error for missing properties in input files.
 Supported for Linux/x86_64.
 
+@item lax-pcrel-relocs
+Relax relocation overflow checks for certain 32-bit PC-relative relocations
+which, when used by 32-bit code inside a 64-bit object, may require a
+larger range of values to be considered valid.
+Supported for x86-64 ELF targets.
+
 @item lazy
 When generating an executable or shared library, mark it to tell the
 dynamic linker to defer function call resolution to the point when
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/code32.d
@@ -0,0 +1,19 @@
+#name: x86-64 R_X86_64_PC32 reloc in 32-bit mode
+#source: ${srcdir}/../../../gas/testsuite/gas/i386/code32.s
+#as: --64 --generate-missing-build-notes=no
+#ld: -T code32.t -z lax-pcrel-relocs
+#objdump: -dw -Mi386
+
+.*: +file format .*
+
+Disassembly of section .text.0:
+
+0+10+ <func0>:
+ +[a-f0-9]+:	e8 fb ff ff 8f       	call   a0000000 <func1>
+ +[a-f0-9]+:	c3                   	ret *
+
+Disassembly of section .text.1:
+
+0+a0+ <func1>:
+ +[a-f0-9]+:	e9 fb ff ff 6f       	jmp    10000000 <func0>
+#pass
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/code32.t
@@ -0,0 +1,7 @@
+OUTPUT_FORMAT("elf64-x86-64")
+OUTPUT_ARCH("i386:x86-64")
+SECTIONS
+{
+  .text.0 0x10000000 : { *(.text.0) }
+  .text.1 0xa0000000 : { *(.text.1) }
+}
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -501,6 +501,7 @@ run_dump_test "property-x86-isa3-x32"
 run_dump_test "property-x86-isa4"
 run_dump_test "property-x86-isa4-x32"
 run_dump_test "code16"
+run_dump_test "code32"
 run_dump_test "pr27491-1a"
 run_dump_test "pr27491-1b"
 run_dump_test "pr27491-1c"


  reply	other threads:[~2022-03-04 13:35 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-04 13:33 [PATCH v2 0/3] x86: another take at PC-relative reloc overflow checking Jan Beulich
2022-03-04 13:34 ` Jan Beulich [this message]
2022-03-04 14:18   ` [PATCH v2 1/3] x86-64/ELF: permit relaxed overflow checking for 32-bit PC-relative relocs H.J. Lu
2022-03-09  8:21     ` Jan Beulich
2022-03-09 14:27       ` H.J. Lu
2022-03-09 14:38         ` Jan Beulich
2022-03-09 15:08           ` H.J. Lu
2022-03-09 15:17             ` Jan Beulich
2022-03-09 15:32               ` H.J. Lu
2022-03-09 15:41                 ` Jan Beulich
2022-03-09 15:54                   ` H.J. Lu
2022-03-09 16:49                     ` Jan Beulich
2022-03-09 18:11                       ` H.J. Lu
2022-03-04 13:35 ` [PATCH v2 2/3] x86-64/ELF: use new reloc override model to deal with x32 special case Jan Beulich
2022-03-04 13:35 ` [PATCH v2 3/3] x86/ELF: permit correct overflow checking for 16-bit PC-relative relocs Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=319f39e5-1f17-23ef-e3fa-2169876aa31c@suse.com \
    --to=jbeulich@suse.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).