[v2,1/3] aarch64: Fix symbol reduction for relocations

Message ID VI2PR83MB0718B21C38D0A0A34B937FFDF8272@VI2PR83MB0718.EURPRD83.prod.outlook.com
State New
Headers
Series aarch64: Relocation fixes and LTO |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Evgeny Karpov Nov. 18, 2024, 11:13 a.m. UTC
  Perhaps initially, "rel->r_type = IMAGE_REL_ARM64_ABSOLUTE" was done
on purpose to bypass changes in processed relocations in a later call
to `_bfd_coff_generic_relocate_section`. However, it was breaking the
relocation reduction logic, as the initial relocation type was no
longer known because PE relocations have been replaced with
IMAGE_REL_ARM64_ABSOLUTE. To avoid extra processing and introducing
an extra field in the relocation structure, rel->r_type =
IMAGE_REL_ARM64_ABSOLUTE has been replaced with rel->r_vaddr = -1,
and a check to skip relocation processing has been added to
_bfd_coff_generic_relocate_section.

In one of the relocation processing steps, there is logic to reduce
a symbol name to a section name where it is placed. In the COFF
format on AArch64, this should not happen for symbols used in
relocations that cannot be fully handled at the object compiling
time. This information will be used by the linker to make correct
relocation. Otherwise, it can lead to a silent relocation overflow
during the linking step because the linker assumes everything looks
good, which most likely results in a crash upon execution.

To resolve this issue, aarch64_fix_adjustable has been
added.

This is the first commit in the patch series
"[PATCH 0/3] aarch64: Relocation fixes and LTO".

Prepared, refactored and validated by
Radek Barton <radek.barton@microsoft.com> and
Evgeny Karpov <evgeny.karpov@microsoft.com>

ChangeLog:

	* bfd/coff-aarch64.c (coff_pe_aarch64_relocate_section):
	Fix relocation.
	* bfd/cofflink.c (_bfd_coff_generic_relocate_section): Likewise.
	* gas/config/tc-aarch64.c (aarch64_fix_adjustable): Add.
	* gas/config/tc-aarch64.h (tc_fix_adjustable): Add.
	(aarch64_fix_adjustable): Add.
---
 bfd/coff-aarch64.c      | 31 +++++++++++--------------------
 bfd/cofflink.c          |  3 +++
 gas/config/tc-aarch64.c | 21 +++++++++++++++++++++
 gas/config/tc-aarch64.h |  6 ++++++
 4 files changed, 41 insertions(+), 20 deletions(-)
  

Patch

diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c
index 3f6a608b728..84af335b3a0 100644
--- a/bfd/coff-aarch64.c
+++ b/bfd/coff-aarch64.c
@@ -579,8 +579,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 		input_section, rel->r_vaddr - input_section->vma);
 
 	    bfd_putl32 (val, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -614,7 +613,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= val & 0x3ffffff;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
+	    rel->r_vaddr = -1;
 
 	    break;
 	  }
@@ -649,8 +648,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= (val & 0x7ffff) << 5;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -684,8 +682,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= (val & 0x3fff) << 5;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -721,7 +718,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= (val & 0x1ffffc) << 3;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
+	    rel->r_vaddr = -1;
 
 	    break;
 	  }
@@ -758,8 +755,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= (val & 0x1ffffc) << 3;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -787,8 +783,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 		input_section, rel->r_vaddr - input_section->vma);
 
 	    bfd_putl32 (val, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -832,8 +827,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= val << 10;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -855,8 +849,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 	    opcode |= val << 10;
 
 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -876,8 +869,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 		input_section, rel->r_vaddr - input_section->vma);
 
 	    bfd_putl32 (val, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
@@ -901,8 +893,7 @@  coff_pe_aarch64_relocate_section (bfd *output_bfd,
 
 
 	    bfd_putl16 (idx, contents + rel->r_vaddr);
-	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
-
+	    rel->r_vaddr = -1;
 	    break;
 	  }
 
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 4a91d5a1833..6cded78c3bb 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -2934,6 +2934,9 @@  _bfd_coff_generic_relocate_section (bfd *output_bfd,
 
       symndx = rel->r_symndx;
 
+      if (rel->r_vaddr == (bfd_vma) -1)
+	continue;
+
       if (symndx == -1)
 	{
 	  h = NULL;
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index e94a0cff406..b515e668822 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -2189,6 +2189,27 @@  s_ltorg (int ignored ATTRIBUTE_UNUSED)
 }
 
 #if defined(OBJ_ELF) || defined(OBJ_COFF)
+
+#if defined OBJ_COFF
+
+bool
+aarch64_fix_adjustable (fixS * fixP)
+{
+  symbolS* sym = fixP->fx_addsy;
+  if (!sym)
+    return true;
+
+  if (S_GET_STORAGE_CLASS (sym) == C_STAT)
+    return false;
+
+  if (symbol_get_bfdsym (sym)->section->flags & (SEC_DATA | SEC_READONLY))
+    return false;
+
+  return true;
+}
+
+#endif
+
 /* Forward declarations for functions below, in the MD interface
    section.  */
 static struct reloc_table_entry * find_reloc_table_entry (char **);
diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h
index 15e22436bf7..f3288a5ae5d 100644
--- a/gas/config/tc-aarch64.h
+++ b/gas/config/tc-aarch64.h
@@ -250,7 +250,12 @@  extern void aarch64_after_parse_args (void);
 #define md_after_parse_args() aarch64_after_parse_args ()
 
 # define EXTERN_FORCE_RELOC 			1
+
+#if defined OBJ_COFF
+# define tc_fix_adjustable(FIX) aarch64_fix_adjustable (FIX)
+#else
 # define tc_fix_adjustable(FIX) 		1
+#endif
 
 /* Values passed to md_apply_fix don't include the symbol value.  */
 # define MD_APPLY_SYM_VALUE(FIX) 		0
@@ -332,6 +337,7 @@  extern void aarch64elf_frob_symbol (symbolS *, int *);
 extern void cons_fix_new_aarch64 (fragS *, int, int, expressionS *);
 extern void aarch64_init_frag (struct frag *, int);
 extern void aarch64_handle_align (struct frag *);
+extern bool aarch64_fix_adjustable (struct fix *);
 extern int tc_aarch64_regname_to_dw2regnum (char *regname);
 extern void tc_aarch64_frame_initial_instructions (void);