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(-)
@@ -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;
}
@@ -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;
@@ -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 **);
@@ -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);