From e0d8c093d06785a19d08e9cd99fef4bc64587ec9 Mon Sep 17 00:00:00 2001 From: Zac Walker Date: Thu, 13 Oct 2022 16:25:50 +0200 Subject: [PATCH] aarch64-pe support for LD, GAS and BFD Allows aarch64-pe to be targeted natively, not having to use objcopy to convert it from ELF to PE. --- bfd/Makefile.am | 2 + bfd/Makefile.in | 1 + bfd/archures.c | 1 + bfd/bfd-in2.h | 1 + bfd/bfd.c | 1 + bfd/coff-aarch64.c | 168 +++++++++++++++++++++++++----- bfd/config.bfd | 16 ++- bfd/configure | 3 +- bfd/configure.ac | 3 +- bfd/cpu-aarch64.c | 35 +++++-- bfd/pe-aarch64.c | 74 +++++++++++++ bfd/pei-aarch64.c | 2 +- bfd/peicode.h | 2 + bfd/po/SRC-POTFILES.in | 1 + bfd/targets.c | 6 +- gas/config/obj-coff.h | 4 + gas/config/tc-aarch64.c | 49 ++++++--- gas/config/tc-aarch64.h | 18 ++-- gas/config/te-pepaarch64.h | 29 ++++++ gas/configure.tgt | 2 +- gas/testsuite/gas/pe/pe-aarch64.d | 14 +++ gas/testsuite/gas/pe/pe-aarch64.s | 11 ++ gas/testsuite/gas/pe/pe.exp | 6 ++ gdb/coff-pe-read.c | 8 +- include/coff/aarch64.h | 22 ++++ ld/Makefile.am | 1 + ld/Makefile.in | 1 + ld/configure.tgt | 6 +- ld/emulparams/aarch64pe.sh | 9 ++ ld/emultempl/pep.em | 10 +- ld/pe-dll.c | 44 ++++++-- ld/pep-dll-aarch64.c | 23 ++++ ld/pep-dll-x86_64.c | 22 ++++ ld/pep-dll.c | 5 +- ld/testsuite/ld-pe/pe-aarch64.d | 16 +++ ld/testsuite/ld-pe/pe-aarch64.s | 11 ++ ld/testsuite/ld-pe/pe.exp | 5 + 37 files changed, 547 insertions(+), 85 deletions(-) create mode 100644 bfd/pe-aarch64.c create mode 100644 gas/config/te-pepaarch64.h create mode 100644 gas/testsuite/gas/pe/pe-aarch64.d create mode 100644 gas/testsuite/gas/pe/pe-aarch64.s create mode 100644 ld/emulparams/aarch64pe.sh create mode 100644 ld/pep-dll-aarch64.c create mode 100644 ld/pep-dll-x86_64.c create mode 100644 ld/testsuite/ld-pe/pe-aarch64.d create mode 100644 ld/testsuite/ld-pe/pe-aarch64.s diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 794d992310..b70d8f3cce 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -578,6 +578,7 @@ BFD64_BACKENDS = \ pe-loongarch64igen.lo \ pe-x86_64.lo \ pei-aarch64.lo \ + pe-aarch64.lo \ pei-ia64.lo \ pei-loongarch64.lo \ pei-x86_64.lo \ @@ -619,6 +620,7 @@ BFD64_BACKENDS_CFILES = \ mach-o-aarch64.c \ mach-o-x86-64.c \ mmo.c \ + pe-aarch64.c \ pe-x86_64.c \ pei-aarch64.c \ pei-ia64.c \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index bdf12c99cf..3f52035582 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -1089,6 +1089,7 @@ BFD64_BACKENDS_CFILES = \ mach-o-aarch64.c \ mach-o-x86-64.c \ mmo.c \ + pe-aarch64.c \ pe-x86_64.c \ pei-aarch64.c \ pei-ia64.c \ diff --git a/bfd/archures.c b/bfd/archures.c index c67bacddfd..e817bb0a44 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -523,6 +523,7 @@ DESCRIPTION .#define bfd_mach_aarch64 0 .#define bfd_mach_aarch64_8R 1 .#define bfd_mach_aarch64_ilp32 32 +.#define bfd_mach_aarch64_llp64 64 . bfd_arch_nios2, {* Nios II. *} .#define bfd_mach_nios2 0 .#define bfd_mach_nios2r1 1 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 25e1806e68..8870d27aa0 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1857,6 +1857,7 @@ enum bfd_architecture #define bfd_mach_aarch64 0 #define bfd_mach_aarch64_8R 1 #define bfd_mach_aarch64_ilp32 32 +#define bfd_mach_aarch64_llp64 64 bfd_arch_nios2, /* Nios II. */ #define bfd_mach_nios2 0 #define bfd_mach_nios2r1 1 diff --git a/bfd/bfd.c b/bfd/bfd.c index 5f2033bee7..6ceda6c469 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -1743,6 +1743,7 @@ bfd_get_sign_extend_vma (bfd *abfd) || strcmp (name, "pei-i386") == 0 || strcmp (name, "pe-x86-64") == 0 || strcmp (name, "pei-x86-64") == 0 + || strcmp (name, "pe-aarch64-little") == 0 || strcmp (name, "pei-aarch64-little") == 0 || strcmp (name, "pe-arm-wince-little") == 0 || strcmp (name, "pei-arm-wince-little") == 0 diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c index e6f2fc2a0a..2c3e225a22 100644 --- a/bfd/coff-aarch64.c +++ b/bfd/coff-aarch64.c @@ -39,34 +39,150 @@ #include "libcoff.h" -/* The page size is a guess based on ELF. */ +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ +#define MINUS_ONE (~ (bfd_vma) 0) + +static const reloc_howto_type arm64_reloc_howto_64 = HOWTO(IMAGE_REL_ARM64_ADDR64, 0, 8, 64, false, 0, + complain_overflow_bitfield, + NULL, "64", + false, MINUS_ONE, MINUS_ONE, false); + +static const reloc_howto_type arm64_reloc_howto_32 = HOWTO (IMAGE_REL_ARM64_ADDR32, 0, 4, 32, false, 0, + complain_overflow_bitfield, + NULL, "32", + false, 0xffffffff, 0xffffffff, false); + +static const reloc_howto_type arm64_reloc_howto_32_pcrel = HOWTO (IMAGE_REL_ARM64_REL32, 0, 4, 32, true, 0, + complain_overflow_bitfield, + NULL, "DISP32", + false, 0xffffffff, 0xffffffff, true); + +static const reloc_howto_type arm64_reloc_howto_branch26 = HOWTO (IMAGE_REL_ARM64_BRANCH26, 0, 4, 26, true, 0, + complain_overflow_bitfield, + NULL, "BRANCH26", + false, 0x03ffffff, 0x03ffffff, true); + +static const reloc_howto_type arm64_reloc_howto_page21 = HOWTO (IMAGE_REL_ARM64_PAGEBASE_REL21, 12, 4, 21, true, 0, + complain_overflow_signed, + NULL, "PAGE21", + false, 0x1fffff, 0x1fffff, false); + +static const reloc_howto_type arm64_reloc_howto_lo21 = HOWTO (IMAGE_REL_ARM64_REL21, 0, 4, 21, true, 0, + complain_overflow_signed, + NULL, "LO21", + false, 0x1fffff, 0x1fffff, true); + +static const reloc_howto_type arm64_reloc_howto_pgoff12 = HOWTO (IMAGE_REL_ARM64_PAGEOFFSET_12L, 1, 4, 12, true, 0, + complain_overflow_signed, + NULL, "PGOFF12", + false, 0xffe, 0xffe, true); + +static const reloc_howto_type arm64_reloc_howto_branch19 = HOWTO (IMAGE_REL_ARM64_BRANCH19, 2, 4, 19, true, 0, + complain_overflow_signed, + NULL, "BRANCH19", + false, 0x7ffff, 0x7ffff, true); + + +static const reloc_howto_type* const arm64_howto_table[] = { + &arm64_reloc_howto_64, + &arm64_reloc_howto_32, + &arm64_reloc_howto_32_pcrel, + &arm64_reloc_howto_branch26, + &arm64_reloc_howto_page21, + &arm64_reloc_howto_lo21, + &arm64_reloc_howto_pgoff12, + &arm64_reloc_howto_branch19 +}; -#define COFF_PAGE_SIZE 0x1000 +#ifndef NUM_ELEM +#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0])) +#endif -/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ -#define OCTETS_PER_BYTE(ABFD, SEC) 1 +#define NUM_RELOCS NUM_ELEM (arm64_howto_table) -#ifndef PCRELOFFSET -#define PCRELOFFSET true -#endif +#define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup +#define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup -/* Currently we don't handle any relocations. */ -static reloc_howto_type pe_aarch64_std_reloc_howto[] = +static reloc_howto_type * +coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) +{ + switch (code) { + case BFD_RELOC_64: + return &arm64_reloc_howto_64; + case BFD_RELOC_32: + return &arm64_reloc_howto_32; + case BFD_RELOC_32_PCREL: + return &arm64_reloc_howto_32_pcrel; + case BFD_RELOC_AARCH64_CALL26: + case BFD_RELOC_AARCH64_JUMP26: + return &arm64_reloc_howto_branch26; + case BFD_RELOC_AARCH64_ADR_HI21_PCREL: + return &arm64_reloc_howto_page21; + case BFD_RELOC_AARCH64_ADR_LO21_PCREL: + return &arm64_reloc_howto_lo21; + case BFD_RELOC_AARCH64_LDST16_LO12: + return &arm64_reloc_howto_pgoff12; + case BFD_RELOC_AARCH64_BRANCH19: + return &arm64_reloc_howto_branch19; + default: + BFD_FAIL (); + return NULL; + } + + return NULL; +} + +static reloc_howto_type * +coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; - }; + for (i = 0; i < NUM_RELOCS; i++) + if (arm64_howto_table[i]->name != NULL + && strcasecmp (arm64_howto_table[i]->name, r_name) == 0) + return arm64_howto_table[i]; + + return NULL; +} #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2 #define COFF_PAGE_SIZE 0x1000 -#ifndef NUM_ELEM -#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0])) -#endif +static reloc_howto_type * +coff_aarch64_rtype_lookup (unsigned int code) +{ + switch (code) + { + case IMAGE_REL_ARM64_ADDR64: + return &arm64_reloc_howto_64; + case IMAGE_REL_ARM64_ADDR32: + return &arm64_reloc_howto_32; + case IMAGE_REL_ARM64_REL32: + return &arm64_reloc_howto_32_pcrel; + case IMAGE_REL_ARM64_BRANCH26: + return &arm64_reloc_howto_branch26; + case IMAGE_REL_ARM64_PAGEBASE_REL21: + return &arm64_reloc_howto_page21; + case IMAGE_REL_ARM64_REL21: + return &arm64_reloc_howto_lo21; + case IMAGE_REL_ARM64_PAGEOFFSET_12L: + return &arm64_reloc_howto_pgoff12; + case IMAGE_REL_ARM64_BRANCH19: + return &arm64_reloc_howto_branch19; + default: + BFD_FAIL (); + return NULL; + } + + return NULL; +} -#define NUM_RELOCS NUM_ELEM (pe_aarch64_std_reloc_howto) +#define RTYPE2HOWTO(cache_ptr, dst) \ + ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type)) -#define RTYPE2HOWTO(cache_ptr, dst) \ - (cache_ptr)->howto = NULL +#define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; } #ifndef bfd_pe_print_pdata #define bfd_pe_print_pdata NULL @@ -93,13 +209,13 @@ const bfd_target #ifdef TARGET_SYM TARGET_SYM = #else - aarch64_pei_vec = +# error "target symbol name not specified" #endif { #ifdef TARGET_NAME TARGET_NAME, #else - "pei-aarch64-little", /* Name. */ +# error "target name not specified" #endif bfd_target_coff_flavour, BFD_ENDIAN_LITTLE, /* Data byte order is little. */ @@ -125,14 +241,14 @@ const bfd_target 0, /* match priority. */ TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ - /* Data conversion functions. */ - bfd_getl64, bfd_getl_signed_64, bfd_putl64, - bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ - /* Header conversion functions. */ - bfd_getl64, bfd_getl_signed_64, bfd_putl64, - bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ + /* Data conversion functions. */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ + /* Header conversion functions. */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ /* Note that we allow an object file to be treated as a core file as well. */ { /* bfd_check_format. */ diff --git a/bfd/config.bfd b/bfd/config.bfd index 5eb82d7e61..0ae8eb39d2 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -245,9 +245,15 @@ case "${targ}" in ;; aarch64-*-elf | aarch64-*-rtems* | aarch64-*-genode*) targ_defvec=aarch64_elf64_le_vec - targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec aarch64_pei_vec" + targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec aarch64_pei_le_vec aarch64_pe_le_vec" want64=true ;; + aarch64-*-pe*) + targ_defvec=aarch64_pe_le_vec + targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec" + want64=true + targ_underscore=no + ;; aarch64_be-*-elf) targ_defvec=aarch64_elf64_be_vec targ_selvecs="aarch64_elf64_le_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_be_vec arm_elf32_le_vec" @@ -280,7 +286,7 @@ case "${targ}" in ;; aarch64-*-linux* | aarch64-*-netbsd*) targ_defvec=aarch64_elf64_le_vec - targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec aarch64_pei_vec" + targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec aarch64_pei_le_vec aarch64_pe_le_vec" want64=true ;; aarch64_be-*-linux* | aarch64_be-*-netbsd*) @@ -1488,6 +1494,12 @@ case "${targ}" in ;; esac +if test x"$targ_defvec" = x"aarch64-pe"; then + # Not currently complete (and probably not stable), warn user + echo "*** WARNING BFD aarch64-pe support not complete nor stable" + echo "*** Do not rely on this for production purposes" +fi + # All MIPS ELF targets need a 64-bit bfd_vma. case "${targ_defvec} ${targ_selvecs}" in *mips_elf*) diff --git a/bfd/configure b/bfd/configure index b72e885f71..bae9d17c51 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13603,7 +13603,8 @@ do aarch64_elf64_le_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;; - aarch64_pei_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; + aarch64_pei_le_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; + aarch64_pe_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;; alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index 7a0ad0ffe3..74c0f07222 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -404,7 +404,8 @@ do aarch64_elf64_le_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_elf64_le_cloudabi_vec) tb="$tb elf64-aarch64.lo elfxx-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;; aarch64_mach_o_vec) tb="$tb mach-o-aarch64.lo"; target_size=64 ;; - aarch64_pei_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; + aarch64_pei_le_vec) tb="$tb pei-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; + aarch64_pe_le_vec) tb="$tb pe-aarch64.lo pe-aarch64igen.lo $coff"; target_size=64 ;; alpha_ecoff_le_vec) tb="$tb coff-alpha.lo ecoff.lo $ecoff"; target_size=64 ;; alpha_elf64_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;; diff --git a/bfd/cpu-aarch64.c b/bfd/cpu-aarch64.c index e1bd8fc478..eb88d0ef86 100644 --- a/bfd/cpu-aarch64.c +++ b/bfd/cpu-aarch64.c @@ -39,8 +39,8 @@ compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b) if (a->mach == b->mach) return a; - /* Don't allow mixing ilp32 with lp64. */ - if ((a->mach & bfd_mach_aarch64_ilp32) != (b->mach & bfd_mach_aarch64_ilp32)) + /* Don't allow mixing data models. */ + if ((a->mach ^ b->mach) & (bfd_mach_aarch64_ilp32 | bfd_mach_aarch64_llp64)) return NULL; /* Otherwise if either a or b is the 'default' machine @@ -102,20 +102,33 @@ scan (const struct bfd_arch_info *info, const char *string) return false; } -#define N(NUMBER, PRINT, WORDSIZE, DEFAULT, NEXT) \ - { WORDSIZE, WORDSIZE, 8, bfd_arch_aarch64, NUMBER, \ - "aarch64", PRINT, 4, DEFAULT, compatible, scan, \ - bfd_arch_default_fill, NEXT, 0 } +/* Figure out if llp64 is default */ +#if DEFAULT_VECTOR == aarch64_pe_le_vec +#define LLP64_DEFAULT true +#define AARCH64_DEFAULT false +#else +#define LLP64_DEFAULT false +#define AARCH64_DEFAULT true +#endif -static const bfd_arch_info_type bfd_aarch64_arch_v8_r = - N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, false, NULL); +#define N(NUMBER, PRINT, WORDSIZE, ADDRSIZE, DEFAULT, NEXT) \ + { WORDSIZE, ADDRSIZE, 8, bfd_arch_aarch64, NUMBER, \ + "aarch64", PRINT, 4, DEFAULT, compatible, scan, \ + bfd_arch_default_fill, NEXT, 0 } + + static const bfd_arch_info_type bfd_aarch64_arch_v8_r = + N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, 64, false, NULL); static const bfd_arch_info_type bfd_aarch64_arch_ilp32 = - N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, false, + N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, 32, false, &bfd_aarch64_arch_v8_r); -const bfd_arch_info_type bfd_aarch64_arch = - N (0, "aarch64", 64, true, &bfd_aarch64_arch_ilp32); +static const bfd_arch_info_type bfd_aarch64_arch_llp64 = + N (bfd_mach_aarch64_llp64, "aarch64:llp64", 32, 64, LLP64_DEFAULT, + &bfd_aarch64_arch_ilp32); + + const bfd_arch_info_type bfd_aarch64_arch = + N (0, "aarch64", 64, 64, AARCH64_DEFAULT, &bfd_aarch64_arch_llp64); bool bfd_is_aarch64_special_symbol_name (const char *name, int type) diff --git a/bfd/pe-aarch64.c b/bfd/pe-aarch64.c new file mode 100644 index 0000000000..0790ba39a1 --- /dev/null +++ b/bfd/pe-aarch64.c @@ -0,0 +1,74 @@ +/* BFD back-end for AArch64 PE IMAGE COFF files. + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" + +#define TARGET_SYM aarch64_pe_le_vec +#define TARGET_NAME "pe-aarch64-little" +#define TARGET_ARCHITECTURE bfd_arch_aarch64 +#define TARGET_PAGESIZE 4096 +#define TARGET_BIG_ENDIAN 0 +#define TARGET_ARCHIVE 0 +#define TARGET_PRIORITY 0 + +/* Rename the above into.. */ +#define COFF_WITH_peAArch64 +#define COFF_WITH_PE +#define PCRELOFFSET true + +/* Long section names not allowed in executable images, only object files. */ +#define COFF_LONG_SECTION_NAMES 1 + +#define COFF_SECTION_ALIGNMENT_ENTRIES \ +{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \ +{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 } + +#define PEI_HEADERS +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "coff/aarch64.h" +#include "coff/internal.h" +#include "coff/pe.h" +#include "libcoff.h" +#include "libpei.h" +#include "libiberty.h" + +/* Make sure we're setting a 64-bit format. */ +#undef AOUTSZ +#define AOUTSZ PEPAOUTSZ +#define PEAOUTHDR PEPAOUTHDR + +#include "coff-aarch64.c" diff --git a/bfd/pei-aarch64.c b/bfd/pei-aarch64.c index c447690793..7b6c681b4b 100644 --- a/bfd/pei-aarch64.c +++ b/bfd/pei-aarch64.c @@ -21,7 +21,7 @@ #include "sysdep.h" #include "bfd.h" -#define TARGET_SYM aarch64_pei_vec +#define TARGET_SYM aarch64_pei_le_vec #define TARGET_NAME "pei-aarch64-little" #define TARGET_ARCHITECTURE bfd_arch_aarch64 #define TARGET_PAGESIZE 4096 diff --git a/bfd/peicode.h b/bfd/peicode.h index 3888dd47cc..add8d82bfd 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -191,6 +191,8 @@ coff_swap_filehdr_in (bfd * abfd, void * src, void * dst) #ifdef COFF_IMAGE_WITH_PE # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out +#elif defined COFF_WITH_peAArch64 +# define coff_swap_filehdr_out _bfd_XX_only_swap_filehdr_out #elif defined COFF_WITH_pex64 # define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out #elif defined COFF_WITH_pep diff --git a/bfd/po/SRC-POTFILES.in b/bfd/po/SRC-POTFILES.in index 30fce580ab..36e51fe063 100644 --- a/bfd/po/SRC-POTFILES.in +++ b/bfd/po/SRC-POTFILES.in @@ -313,6 +313,7 @@ osf-core.c pc532-mach.c pdb.c pdp11.c +pe-aarch64.c pe-arm-wince.c pe-arm.c pe-i386.c diff --git a/bfd/targets.c b/bfd/targets.c index 7dbc3a5dbf..0bb85b64cc 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -686,7 +686,8 @@ extern const bfd_target aarch64_elf64_be_cloudabi_vec; extern const bfd_target aarch64_elf64_le_vec; extern const bfd_target aarch64_elf64_le_cloudabi_vec; extern const bfd_target aarch64_mach_o_vec; -extern const bfd_target aarch64_pei_vec; +extern const bfd_target aarch64_pei_le_vec; +extern const bfd_target aarch64_pe_le_vec; extern const bfd_target alpha_ecoff_le_vec; extern const bfd_target alpha_elf64_vec; extern const bfd_target alpha_elf64_fbsd_vec; @@ -999,7 +1000,8 @@ static const bfd_target * const _bfd_target_vector[] = &aarch64_elf64_le_vec, &aarch64_elf64_le_cloudabi_vec, &aarch64_mach_o_vec, - &aarch64_pei_vec, + &aarch64_pe_le_vec, + &aarch64_pei_le_vec, #endif #ifdef BFD64 diff --git a/gas/config/obj-coff.h b/gas/config/obj-coff.h index 1dbd38aea3..f79c73702f 100644 --- a/gas/config/obj-coff.h +++ b/gas/config/obj-coff.h @@ -40,6 +40,10 @@ #endif #endif +#ifdef TC_AARCH64 +#include "coff/aarch64.h" +#endif + #ifdef TC_PPC #include "coff/rs6000.h" #endif diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 98a7ca5878..f6fa158583 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -30,9 +30,9 @@ #ifdef OBJ_ELF #include "elf/aarch64.h" -#include "dw2gencfi.h" #endif +#include "dw2gencfi.h" #include "dwarf2dbg.h" /* Types of processor to assemble for. */ @@ -61,21 +61,25 @@ static aarch64_instr_sequence *insn_sequence = NULL; #ifdef OBJ_ELF /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ static symbolS *GOT_symbol; +#endif /* Which ABI to use. */ enum aarch64_abi_type { AARCH64_ABI_NONE = 0, AARCH64_ABI_LP64 = 1, - AARCH64_ABI_ILP32 = 2 + AARCH64_ABI_ILP32 = 2, + AARCH64_ABI_LLP64 = 3 }; #ifndef DEFAULT_ARCH #define DEFAULT_ARCH "aarch64" #endif +#ifdef OBJ_ELF /* DEFAULT_ARCH is initialized in gas/configure.tgt. */ static const char *default_arch = DEFAULT_ARCH; +#endif /* AArch64 ABI for the output file. */ static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_NONE; @@ -85,7 +89,10 @@ static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_NONE; 64-bit model, in which the C int type is 32-bits but the C long type and all pointer types are 64-bit objects (LP64). */ #define ilp32_p (aarch64_abi == AARCH64_ABI_ILP32) -#endif + +/* When non zero, C types int and long are 32 bit, + pointers, however are 64 bit */ +#define llp64_p (aarch64_abi == AARCH64_ABI_LLP64) enum vector_el_type { @@ -1459,7 +1466,7 @@ s_unreq (int a ATTRIBUTE_UNUSED) /* Directives: Instruction set selection. */ -#ifdef OBJ_ELF +#if defined OBJ_ELF || defined OBJ_COFF /* This code is to handle mapping symbols as defined in the ARM AArch64 ELF spec. (See "Mapping symbols", section 4.5.4, ARM AAELF64 version 0.05). Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag), @@ -8336,7 +8343,7 @@ aarch64_handle_align (fragS * fragP) fix = bytes & (noop_size - 1); if (fix) { -#ifdef OBJ_ELF +#if defined OBJ_ELF || defined OBJ_COFF insert_data_mapping_symbol (MAP_INSN, fragP->fr_fix, fragP, fix); #endif memset (p, 0, fix); @@ -8394,6 +8401,7 @@ aarch64_init_frag (fragS * fragP, int max_chars) break; } } +#endif /* OBJ_ELF */ /* Initialize the DWARF-2 unwind information for this procedure. */ @@ -8402,7 +8410,6 @@ tc_aarch64_frame_initial_instructions (void) { cfi_add_CFA_def_cfa (REG_SP, 0); } -#endif /* OBJ_ELF */ /* Convert REGNAME to a DWARF-2 register number. */ @@ -8439,10 +8446,10 @@ tc_aarch64_regname_to_dw2regnum (char *regname) int aarch64_dwarf2_addr_size (void) { -#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) if (ilp32_p) return 4; -#endif + else if (llp64_p) + return 8; return bfd_arch_bits_per_address (stdoutput) / 8; } @@ -9307,8 +9314,6 @@ cons_fix_new_aarch64 (fragS * frag, int where, int size, expressionS * exp) fix_new_exp (frag, where, (int) size, exp, pcrel, type); } -#ifdef OBJ_ELF - /* Implement md_after_parse_args. This is the earliest time we need to decide ABI. If no -mabi specified, the ABI will be decided by target triplet. */ @@ -9318,13 +9323,18 @@ aarch64_after_parse_args (void) if (aarch64_abi != AARCH64_ABI_NONE) return; +#ifdef OBJ_ELF /* DEFAULT_ARCH will have ":32" extension if it's configured for ILP32. */ if (strlen (default_arch) > 7 && strcmp (default_arch + 7, ":32") == 0) aarch64_abi = AARCH64_ABI_ILP32; else aarch64_abi = AARCH64_ABI_LP64; +#else + aarch64_abi = AARCH64_ABI_LLP64; +#endif } +#ifdef OBJ_ELF const char * elf64_aarch64_target_format (void) { @@ -9347,6 +9357,12 @@ aarch64elf_frob_symbol (symbolS * symp, int *puntp) { elf_frob_symbol (symp, puntp); } +#elif defined OBJ_COFF +const char * +coff_aarch64_target_format (void) +{ + return "pe-aarch64-little"; +} #endif /* MD interface: Finalization. */ @@ -9662,7 +9678,12 @@ md_begin (void) cpu_variant = *mcpu_cpu_opt; /* Record the CPU type. */ - mach = ilp32_p ? bfd_mach_aarch64_ilp32 : bfd_mach_aarch64; + if(ilp32_p) + mach = bfd_mach_aarch64_ilp32; + else if (llp64_p) + mach = bfd_mach_aarch64_llp64; + else + mach = bfd_mach_aarch64; bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach); } @@ -10230,8 +10251,12 @@ struct aarch64_option_abi_value_table }; static const struct aarch64_option_abi_value_table aarch64_abis[] = { +#ifdef OBJ_ELF {"ilp32", AARCH64_ABI_ILP32}, {"lp64", AARCH64_ABI_LP64}, +#else + {"llp64", AARCH64_ABI_LLP64}, +#endif }; static int @@ -10257,10 +10282,8 @@ aarch64_parse_abi (const char *str) } static struct aarch64_long_option_table aarch64_long_opts[] = { -#ifdef OBJ_ELF {"mabi=", N_("\t specify for ABI "), aarch64_parse_abi, NULL}, -#endif /* OBJ_ELF */ {"mcpu=", N_("\t assemble for CPU "), aarch64_parse_cpu, NULL}, {"march=", N_("\t assemble for architecture "), diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h index f5c1752379..2d514ff610 100644 --- a/gas/config/tc-aarch64.h +++ b/gas/config/tc-aarch64.h @@ -59,9 +59,11 @@ struct aarch64_fix enum aarch64_opnd opnd; }; -#if defined OBJ_ELF +#ifdef OBJ_ELF # define AARCH64_BI_ENDIAN # define TARGET_FORMAT elf64_aarch64_target_format () +#elif defined (OBJ_COFF) +# define TARGET_FORMAT coff_aarch64_target_format () #endif #define TC_FORCE_RELOCATION(FIX) aarch64_force_relocation (FIX) @@ -169,7 +171,7 @@ void aarch64_elf_copy_symbol_attributes (symbolS *, symbolS *); struct aarch64_frag_type { int recorded; -#ifdef OBJ_ELF +#if defined OBJ_ELF || defined OBJ_COFF /* If there is a mapping symbol at offset 0 in this frag, it will be saved in FIRST_MAP. If there are any mapping symbols in this frag, the last one will be saved in @@ -202,8 +204,10 @@ struct aarch64_frag_type extern int aarch64_dwarf2_addr_size (void); #define DWARF2_ADDR_SIZE(bfd) aarch64_dwarf2_addr_size () +#if defined OBJ_ELF || defined OBJ_COFF #ifdef OBJ_ELF # define obj_frob_symbol(sym, punt) aarch64elf_frob_symbol ((sym), & (punt)) +#endif # define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" # define TC_SEGMENT_INFO_TYPE struct aarch64_segment_info_type @@ -259,6 +263,7 @@ extern void aarch64_after_parse_args (void); extern void aarch64_frag_align_code (int, int); extern const char * elf64_aarch64_target_format (void); +extern const char * coff_aarch64_target_format (void); extern int aarch64_force_relocation (struct fix *); extern void aarch64_cleanup (void); extern void aarch64_start_line_hook (void); @@ -274,13 +279,4 @@ extern void aarch64_handle_align (struct frag *); extern int tc_aarch64_regname_to_dw2regnum (char *regname); extern void tc_aarch64_frame_initial_instructions (void); -#ifdef TE_PE - -#define O_secrel O_md1 - -#define TC_DWARF2_EMIT_OFFSET tc_pe_dwarf2_emit_offset -void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int); - -#endif /* TE_PE */ - #endif /* TC_AARCH64 */ diff --git a/gas/config/te-pepaarch64.h b/gas/config/te-pepaarch64.h new file mode 100644 index 0000000000..4774e94a63 --- /dev/null +++ b/gas/config/te-pepaarch64.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2006-2022 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, + or (at your option) any later version. + + GAS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#define TE_PEP +#define COFF_WITH_peAArch64 + +#define TE_PE +#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels. */ + +/* The PE format supports long section names. */ +#define COFF_LONG_SECTION_NAMES + +#include "obj-format.h" diff --git a/gas/configure.tgt b/gas/configure.tgt index 9f2b6720bd..82f2d44f41 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -135,7 +135,7 @@ case ${generic_target} in esac ;; aarch64*-*-netbsd*) fmt=elf em=nbsd;; aarch64*-*-openbsd*) fmt=elf;; - + aarch64*-*-pe*) fmt=coff em=pepaarch64 ;; alpha-*-*vms*) fmt=evax ;; alpha-*-osf*) fmt=ecoff ;; alpha-*-linux*ecoff*) fmt=ecoff ;; diff --git a/gas/testsuite/gas/pe/pe-aarch64.d b/gas/testsuite/gas/pe/pe-aarch64.d new file mode 100644 index 0000000000..0b8009da5c --- /dev/null +++ b/gas/testsuite/gas/pe/pe-aarch64.d @@ -0,0 +1,14 @@ +#as: +#objdump: -d + +.*: file format pe-aarch64-little + + +Disassembly of section .text: + +0000000000000000 <_start>: + 0: d2800281 mov x1, #0x14 // #20 + 4: 14000001 b 8 + +0000000000000008 : + 8: d65f03c0 ret diff --git a/gas/testsuite/gas/pe/pe-aarch64.s b/gas/testsuite/gas/pe/pe-aarch64.s new file mode 100644 index 0000000000..546d55fc36 --- /dev/null +++ b/gas/testsuite/gas/pe/pe-aarch64.s @@ -0,0 +1,11 @@ +# A little test to ensure pe-aarch64 is working in GAS. +# Currently, the poor pe-aarch64 implementation in binutils +# couldn't do anything useful, hence, this test is rather short + +.section .text + +_start: + mov x1, 20 + b foo +foo: + ret diff --git a/gas/testsuite/gas/pe/pe.exp b/gas/testsuite/gas/pe/pe.exp index 3568ff7b02..8df750f9dd 100644 --- a/gas/testsuite/gas/pe/pe.exp +++ b/gas/testsuite/gas/pe/pe.exp @@ -52,6 +52,12 @@ if ([istarget "x86_64-*-mingw*"]) then { run_dump_test "peseh-x64-6" } + +# This test is only for AArch64 +if ([istarget "aarch64-*-pe*"]) { + run_dump_test "pe-aarch64" +} + # Big obj diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c index 2f3b80815b..0f57deb391 100644 --- a/gdb/coff-pe-read.c +++ b/gdb/coff-pe-read.c @@ -331,7 +331,9 @@ read_pe_exported_syms (minimal_symbol_reader &reader, section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; is_pe64 = (strcmp (target, "pe-x86-64") == 0 - || strcmp (target, "pei-x86-64") == 0); + || strcmp (target, "pei-x86-64") == 0 + || strcmp (target, "pe-aarch64") == 0 + || strcmp (target, "pei-aarch64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 @@ -610,7 +612,9 @@ pe_text_section_offset (struct bfd *abfd) target = bfd_get_target (abfd); is_pe64 = (strcmp (target, "pe-x86-64") == 0 - || strcmp (target, "pei-x86-64") == 0); + || strcmp (target, "pei-x86-64") == 0 + || strcmp (target, "pe-aarch64") == 0 + || strcmp (target, "pei-aarch64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 diff --git a/include/coff/aarch64.h b/include/coff/aarch64.h index 2bbeaa9fad..100e08f18e 100644 --- a/include/coff/aarch64.h +++ b/include/coff/aarch64.h @@ -60,4 +60,26 @@ struct external_reloc #define RELOC struct external_reloc #define RELSZ 14 +/* ARM64 relocations types. */ + + +#define IMAGE_REL_ARM64_ABSOLUTE 0x0000 /* No relocation required */ +#define IMAGE_REL_ARM64_ADDR32 0x0001 /* The 32-bit VA of the target. */ +#define IMAGE_REL_ARM64_ADDR32NB 0x0002 /* The 32-bit RVA of the target. */ +#define IMAGE_REL_ARM64_BRANCH26 0x0003 /* The 26-bit relative displacement to the target, for B and BL instructions. */ +#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004 /* The page base of the target, for ADRP instruction. */ +#define IMAGE_REL_ARM64_REL21 0x0005 /* The 12-bit relative displacement to the target, for instruction ADR */ +#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006 /* The 12-bit page offset of the target, for instructions ADD/ADDS (immediate) with zero shift. */ +#define IMAGE_REL_ARM64_PAGEOFFSET_12L 0x0007 /* The 12-bit page offset of the target, for instruction LDR (indexed, unsigned immediate). */ +#define IMAGE_REL_ARM64_SECREL 0x0008 /* The 32-bit offset of the target from the beginning of its section. This is used to support debugging information and static thread local storage. */ +#define IMAGE_REL_ARM64_SECREL_LOW12A 0x0009 /* Bit 0:11 of section offset of the target, for instructions ADD/ADDS (immediate) with zero shift. */ +#define IMAGE_REL_ARM64_SECREL_HIGH12A 0x000A /* Bit 12:23 of section offset of the target, for instructions ADD/ADDS (immediate) with zero shift. */ +#define IMAGE_REL_ARM64_SECREL_LOW12L 0x000B /* Bit 0:11 of section offset of the target, for instruction LDR (indexed, unsigned immediate). */ +#define IMAGE_REL_ARM64_TOKEN 0x000C /* CLR token */ +#define IMAGE_REL_ARM64_SECTION 0x000D /* The 16-bit section index of the section that contains the target. This is used to support debugging information. */ +#define IMAGE_REL_ARM64_ADDR64 0x000E /* The 64-bit VA of the relocation target. */ +#define IMAGE_REL_ARM64_BRANCH19 0x000F /* 19 bit offset << 2 & sign ext. for conditional B */ +#define IMAGE_REL_ARM64_BRANCH14 0x0010 /* The 14-bit offset to the relocation target, for instructions TBZ and TBNZ. */ +#define IMAGE_REL_ARM64_REL32 0x0011 /* The 32-bit relative address from the byte following the relocation. */ + #define ARM_NOTE_SECTION ".note" diff --git a/ld/Makefile.am b/ld/Makefile.am index bbe25f3aca..b4ec47ae1f 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -377,6 +377,7 @@ ALL_EMULATIONS = $(ALL_EMULATION_SOURCES:.c=.@OBJEXT@) ALL_64_EMULATION_SOURCES = \ eaarch64cloudabi.c \ eaarch64cloudabib.c \ + eaarch64pe.c \ eaarch64elf.c \ eaarch64elf32.c \ eaarch64elf32b.c \ diff --git a/ld/Makefile.in b/ld/Makefile.in index 400eed2717..21d7edb410 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -887,6 +887,7 @@ ALL_64_EMULATION_SOURCES = \ eaarch64linux32.c \ eaarch64linux32b.c \ eaarch64linuxb.c \ + eaarch64pe.c \ eelf32_x86_64.c \ eelf32b4300.c \ eelf32bmip.c \ diff --git a/ld/configure.tgt b/ld/configure.tgt index 2bae9099b6..97639880d7 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -117,6 +117,10 @@ aarch64-*-linux*) targ_emul=aarch64linux aarch64-*-haiku*) targ_emul=aarch64haiku targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b aarch64elfb armelf armelfb armelf_haiku $targ_extra_libpath" ;; +aarch64-*-pe*) + targ_emul=aarch64pe + targ_extra_ofiles="deffilep.o pep-dll-aarch64.o" + ;; alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu) targ_emul=elf64alpha_fbsd targ_extra_emuls="elf64alpha alpha" @@ -1042,7 +1046,7 @@ x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) ;; x86_64-*-pe | x86_64-*-pep) targ_emul=i386pep ; targ_extra_emuls=i386pe ; - targ_extra_ofiles="deffilep.o pep-dll.o pe-dll.o" + targ_extra_ofiles="deffilep.o pep-dll-x86_64.o pe-dll.o" ;; x86_64-*-cygwin) targ_emul=i386pep ; targ_extra_emuls=i386pe diff --git a/ld/emulparams/aarch64pe.sh b/ld/emulparams/aarch64pe.sh new file mode 100644 index 0000000000..02bf02cd96 --- /dev/null +++ b/ld/emulparams/aarch64pe.sh @@ -0,0 +1,9 @@ +ARCH="aarch64" +SCRIPT_NAME=pep +OUTPUT_FORMAT="pei-aarch64-little" +RELOCATEABLE_OUTPUT_FORMAT="pe-aarch64-little" +TEMPLATE_NAME=pep +SUBSYSTEM=PE_DEF_SUBSYSTEM +INITIAL_SYMBOL_CHAR=\"_\" +TARGET_PAGE_SIZE=0x1000 +GENERATE_AUTO_IMPORT_SCRIPT=1 diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index d94f18b05c..7a390e74b0 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -48,7 +48,11 @@ fragment <howto->bitsize, relocs[i]->howto->rightshift) { -#ifdef pe_use_x86_64 +#ifdef pe_use_plus case BITS_AND_SHIFT (64, 0): reloc_data[total_relocs].type = IMAGE_REL_BASED_DIR64; total_relocs++; @@ -2247,6 +2257,15 @@ static const unsigned char jmp_ix86_bytes[] = 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 }; +/* _function: + b <__imp_function> + nop */ +static const unsigned char jmp_aarch64_bytes[] = +{ + 0x00, 0x00, 0x00, 0x14, + 0x1f, 0x20, 0x03, 0xD5 +}; + /* _function: mov.l ip+8,r0 mov.l @r0,r0 @@ -2317,6 +2336,10 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub) jmp_bytes = jmp_arm_bytes; jmp_byte_count = sizeof (jmp_arm_bytes); break; + case PE_ARCH_aarch64: + jmp_bytes = jmp_aarch64_bytes; + jmp_byte_count = sizeof (jmp_aarch64_bytes); + break; default: abort (); } @@ -2386,7 +2409,7 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub) switch (pe_details->pe_arch) { case PE_ARCH_i386: -#ifdef pe_use_x86_64 +#ifdef pe_use_plus quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2); #else /* Mark this object as SAFESEH compatible. */ @@ -2407,6 +2430,9 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub) case PE_ARCH_arm_wince: quick_reloc (abfd, 8, BFD_RELOC_32, 2); break; + case PE_ARCH_aarch64: + quick_reloc (abfd, 0, BFD_RELOC_AARCH64_JUMP26, 2); + break; default: abort (); } @@ -3406,7 +3432,7 @@ pe_implied_import_dll (const char *filename) /* Get pe_header, optional header and numbers of directory entries. */ pe_header_offset = pe_get32 (dll, 0x3c); opthdr_ofs = pe_header_offset + 4 + 20; -#ifdef pe_use_x86_64 +#ifdef pe_use_plus num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */ #else num_entries = pe_get32 (dll, opthdr_ofs + 92); @@ -3416,7 +3442,7 @@ pe_implied_import_dll (const char *filename) if (num_entries < 1) return false; -#ifdef pe_use_x86_64 +#ifdef pe_use_plus export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4); export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4); #else diff --git a/ld/pep-dll-aarch64.c b/ld/pep-dll-aarch64.c new file mode 100644 index 0000000000..61c9a2a2c9 --- /dev/null +++ b/ld/pep-dll-aarch64.c @@ -0,0 +1,23 @@ +/* Tiny wrapper over pep-dll.c + Copyright (C) 2006-2022 Free Software Foundation, Inc. + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define COFF_WITH_peAArch64 + +#include "pep-dll.c" diff --git a/ld/pep-dll-x86_64.c b/ld/pep-dll-x86_64.c new file mode 100644 index 0000000000..0be189815c --- /dev/null +++ b/ld/pep-dll-x86_64.c @@ -0,0 +1,22 @@ +/* Tiny wrapper over pep-dll.c + Copyright (C) 2006-2022 Free Software Foundation, Inc. + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define COFF_WITH_pex64 + +#include "pep-dll.c" diff --git a/ld/pep-dll.c b/ld/pep-dll.c index 3049a024e1..1cfed49033 100644 --- a/ld/pep-dll.c +++ b/ld/pep-dll.c @@ -21,7 +21,6 @@ #define COFF_IMAGE_WITH_PE #define COFF_WITH_PE -#define COFF_WITH_pex64 /* Local defined globals. */ #define pe_def_file pep_def_file @@ -58,7 +57,7 @@ #define pe_output_file_set_long_section_names \ pep_output_file_set_long_section_names -/* Uses x86_64 PE+. */ -#define pe_use_x86_64 +/* Uses PE+. */ +#define pe_use_plus #include "pe-dll.c" diff --git a/ld/testsuite/ld-pe/pe-aarch64.d b/ld/testsuite/ld-pe/pe-aarch64.d new file mode 100644 index 0000000000..fac02b5fd8 --- /dev/null +++ b/ld/testsuite/ld-pe/pe-aarch64.d @@ -0,0 +1,16 @@ +#ld: +#objdump: -d + +.*: file format pei-aarch64-little + + +Disassembly of section .text: + +0000000140001000 <__rt_psrelocs_end>: + 140001000: d2800281 mov x1, #0x14 // #20 + 140001004: 14000001 b 140001008 + +0000000140001008 : + 140001008: d65f03c0 ret + 14000100c: 00000000 udf #0 +#... diff --git a/ld/testsuite/ld-pe/pe-aarch64.s b/ld/testsuite/ld-pe/pe-aarch64.s new file mode 100644 index 0000000000..5d49350891 --- /dev/null +++ b/ld/testsuite/ld-pe/pe-aarch64.s @@ -0,0 +1,11 @@ +# A little test to ensure pe-aarch64 is working in LD. +# Currently, the poor pe-aarch64 implementation in binutils +# couldn't do anything useful, hence, this test is rather short + +.section .text + +_start: + mov x1, 20 + b foo +foo: + ret diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp index 22819e0894..d8595ee61e 100644 --- a/ld/testsuite/ld-pe/pe.exp +++ b/ld/testsuite/ld-pe/pe.exp @@ -78,6 +78,11 @@ if {[istarget i*86-*-cygwin*] run_ld_link_tests $pe_tests } +if {[istarget "aarch64-*-pe*"]} { + run_dump_test "pe-aarch64" +} + + run_dump_test "image_size" run_dump_test "export_dynamic_warning" -- 2.25.1