Move x86_64 PE changes out of bfd_perform_relocation
authorAlan Modra <amodra@gmail.com>
Thu, 4 Mar 2021 12:28:54 +0000 (22:58 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 5 Mar 2021 04:27:42 +0000 (14:57 +1030)
bfd_perform_relocation should not have special case target code.  This
patch moves the code that was there for x86_64 PE linking to ELF
output into the x86_64 PE howto special function, correcting that
function for linking to targets other than ELF too.  The fixes in
bfd_perform_relocation were over-complicated due to needing to
compensate for things that had already gone wrong in coff_amd64_reloc.
In particular, an adjustment for pc-relative relocs was done in a way
that meant adjustment for things related to symbol offsets was lost.
I think those two things are orthogonal, but who knows with COFF where
addends and symbol values are found randomly in the section contents.

Note that linking natively to an x86_64 PE output relocates by
coff_pe_amd64_relocate_section, which does not use arelent relocs or
bfd_perform_relocation, but be aware of coff_amd64_rtype_to_howto
hacking addends for relocations.  The adjustments for a particular
relocation type there and in coff_amd64_reloc ought to match after
taking into consideration CALC_ADDEND.  They don't.  For example,
the pc-relative adjustment for R_PCRWORD is 2 bytes in
coff_amd64_reloc and 4 bytes in coff_amd64_rtype_to_howto.

* reloc.c (bfd_perform_relocation): Revert 2021-01-12 and
2020-09-16 changes.
* coff-x86_64.c (coff_amd64_reloc): Do more or less the same
adjustments here instead.  Separate pc-relative adjustments
from symbol related adjustments.  Tidy comments and formatting.

bfd/ChangeLog
bfd/coff-x86_64.c
bfd/reloc.c

index 7379e7b80b7e377d13c6e1ba9e8bfa65c3e4a6c9..bc1a530a9dbcf0fbfb9abf1c72f1b3589b568fff 100644 (file)
@@ -1,3 +1,11 @@
+2021-03-05  Alan Modra  <amodra@gmail.com>
+
+       * reloc.c (bfd_perform_relocation): Revert 2021-01-12 and
+       2020-09-16 changes.
+       * coff-x86_64.c (coff_amd64_reloc): Do more or less the same
+       adjustments here instead.  Separate pc-relative adjustments
+       from symbol related adjustments.  Tidy comments and formatting.
+
 2021-03-04  Jan Beulich  <jbeulich@suse.com>
 
        * coffcode.h (sec_to_styp_flags): Don't set IMAGE_SCN_LNK_* in
index adab60cd113fd91aae2a92bed733c9106d97ddd7..5b09023f3c229c497a2828db44d937955dbeb14a 100644 (file)
@@ -75,14 +75,14 @@ coff_amd64_reloc (bfd *abfd,
 {
   symvalue diff;
 
-#if !defined(COFF_WITH_PE)
+#if !defined (COFF_WITH_PE)
   if (output_bfd == NULL)
     return bfd_reloc_continue;
 #endif
 
   if (bfd_is_com_section (symbol->section))
     {
-#if !defined(COFF_WITH_PE)
+#if !defined (COFF_WITH_PE)
       /* We are relocating a common symbol.  The current value in the
         object file is ORIG + OFFSET, where ORIG is the value of the
         common symbol as seen by the object file when it was compiled
@@ -106,21 +106,10 @@ coff_amd64_reloc (bfd *abfd,
         ignores the addend for a COFF target when producing
         relocatable output.  This seems to be always wrong for 386
         COFF, so we handle the addend here instead.  */
-#if defined(COFF_WITH_PE)
+#if defined (COFF_WITH_PE)
       if (output_bfd == NULL)
        {
-         reloc_howto_type *howto = reloc_entry->howto;
-
-         /* Although PC relative relocations are very similar between
-            PE and non-PE formats, but they are off by 1 << howto->size
-            bytes. For the external relocation, PE is very different
-            from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
-            When we link PE and non-PE object files together to
-            generate a non-PE executable, we have to compensate it
-            here.  */
-         if(howto->pc_relative && howto->pcrel_offset)
-           diff = -(1 << howto->size);
-         else if(symbol->flags & BSF_WEAK)
+         if (symbol->flags & BSF_WEAK)
            diff = reloc_entry->addend - symbol->value;
          else
            diff = -reloc_entry->addend;
@@ -130,7 +119,18 @@ coff_amd64_reloc (bfd *abfd,
        diff = reloc_entry->addend;
     }
 
-#if defined(COFF_WITH_PE)
+#if defined (COFF_WITH_PE)
+  if (output_bfd == NULL)
+    {
+      /* PC relative relocations are off by their size.  */
+      if (reloc_entry->howto->pc_relative)
+       diff -= bfd_get_reloc_size (reloc_entry->howto);
+
+      if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1
+         && reloc_entry->howto->type <= R_AMD64_PCRLONG_5)
+       diff -= reloc_entry->howto->type - R_AMD64_PCRLONG;
+    }
+
   /* FIXME: How should this case be handled?  */
   if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
       && output_bfd != NULL
index a7547187ebeef370fb8cd29301225e55fd7fcd22..5ed7bb8e5960d3a8ee3c974a57ba928a41bb1d45 100644 (file)
@@ -51,7 +51,7 @@ SECTION
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "bfdver.h"
-#include "coff/x86_64.h"
+
 /*
 DOCDD
 INODE
@@ -905,30 +905,6 @@ space consuming.  For each target:
            }
        }
     }
-  else if (abfd->xvec->flavour == bfd_target_coff_flavour
-          && (input_section->output_section->owner->xvec->flavour
-              == bfd_target_elf_flavour)
-          && strcmp (abfd->xvec->name, "pe-x86-64") == 0
-          && strcmp (input_section->output_section->owner->xvec->name,
-                     "elf64-x86-64") == 0)
-    {
-      /* NB: bfd_perform_relocation isn't called to generate PE binary.
-        _bfd_relocate_contents is called instead.  When linking PE
-        object files to generate ELF output, _bfd_relocate_contents
-        isn't called and bfd_perform_relocation is used.  We need to
-        adjust relocation here.  */
-      relocation -= reloc_entry->addend;
-      if (howto->type >= R_AMD64_PCRLONG_1
-         && howto->type <= R_AMD64_PCRLONG_5)
-       relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG);
-      else if (howto->type == R_AMD64_DIR64
-              || howto->type == R_AMD64_DIR32)
-       {
-         bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets,
-                                   howto);
-         relocation -= val & howto->src_mask;
-       }
-    }
 
   /* FIXME: This overflow checking is incomplete, because the value
      might have overflowed before we get here.  For a correct check we