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.
Based on initial work by Jedidiah Thompson

Co-authored-by: Jedidiah Thompson <wej22007@outlook.com>
Co-authored-by: Zac Walker <zac.walker@linaro.org>
This commit is contained in:
Jedidiah Thompson
2022-10-19 10:57:12 +02:00
committed by Zac Walker
parent 740a19d914
commit c60b380679
37 changed files with 547 additions and 85 deletions

View File

@ -578,6 +578,7 @@ BFD64_BACKENDS = \
pe-loongarch64igen.lo \ pe-loongarch64igen.lo \
pe-x86_64.lo \ pe-x86_64.lo \
pei-aarch64.lo \ pei-aarch64.lo \
pe-aarch64.lo \
pei-ia64.lo \ pei-ia64.lo \
pei-loongarch64.lo \ pei-loongarch64.lo \
pei-x86_64.lo \ pei-x86_64.lo \
@ -619,6 +620,7 @@ BFD64_BACKENDS_CFILES = \
mach-o-aarch64.c \ mach-o-aarch64.c \
mach-o-x86-64.c \ mach-o-x86-64.c \
mmo.c \ mmo.c \
pe-aarch64.c \
pe-x86_64.c \ pe-x86_64.c \
pei-aarch64.c \ pei-aarch64.c \
pei-ia64.c \ pei-ia64.c \

View File

@ -1089,6 +1089,7 @@ BFD64_BACKENDS_CFILES = \
mach-o-aarch64.c \ mach-o-aarch64.c \
mach-o-x86-64.c \ mach-o-x86-64.c \
mmo.c \ mmo.c \
pe-aarch64.c \
pe-x86_64.c \ pe-x86_64.c \
pei-aarch64.c \ pei-aarch64.c \
pei-ia64.c \ pei-ia64.c \

View File

@ -523,6 +523,7 @@ DESCRIPTION
.#define bfd_mach_aarch64 0 .#define bfd_mach_aarch64 0
.#define bfd_mach_aarch64_8R 1 .#define bfd_mach_aarch64_8R 1
.#define bfd_mach_aarch64_ilp32 32 .#define bfd_mach_aarch64_ilp32 32
.#define bfd_mach_aarch64_llp64 64
. bfd_arch_nios2, {* Nios II. *} . bfd_arch_nios2, {* Nios II. *}
.#define bfd_mach_nios2 0 .#define bfd_mach_nios2 0
.#define bfd_mach_nios2r1 1 .#define bfd_mach_nios2r1 1

View File

@ -1857,6 +1857,7 @@ enum bfd_architecture
#define bfd_mach_aarch64 0 #define bfd_mach_aarch64 0
#define bfd_mach_aarch64_8R 1 #define bfd_mach_aarch64_8R 1
#define bfd_mach_aarch64_ilp32 32 #define bfd_mach_aarch64_ilp32 32
#define bfd_mach_aarch64_llp64 64
bfd_arch_nios2, /* Nios II. */ bfd_arch_nios2, /* Nios II. */
#define bfd_mach_nios2 0 #define bfd_mach_nios2 0
#define bfd_mach_nios2r1 1 #define bfd_mach_nios2r1 1

View File

@ -1743,6 +1743,7 @@ bfd_get_sign_extend_vma (bfd *abfd)
|| strcmp (name, "pei-i386") == 0 || strcmp (name, "pei-i386") == 0
|| strcmp (name, "pe-x86-64") == 0 || strcmp (name, "pe-x86-64") == 0
|| strcmp (name, "pei-x86-64") == 0 || strcmp (name, "pei-x86-64") == 0
|| strcmp (name, "pe-aarch64-little") == 0
|| strcmp (name, "pei-aarch64-little") == 0 || strcmp (name, "pei-aarch64-little") == 0
|| strcmp (name, "pe-arm-wince-little") == 0 || strcmp (name, "pe-arm-wince-little") == 0
|| strcmp (name, "pei-arm-wince-little") == 0 || strcmp (name, "pei-arm-wince-little") == 0

View File

@ -39,34 +39,150 @@
#include "libcoff.h" #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)
#define COFF_PAGE_SIZE 0x1000 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);
/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ static const reloc_howto_type arm64_reloc_howto_32 = HOWTO (IMAGE_REL_ARM64_ADDR32, 0, 4, 32, false, 0,
#define OCTETS_PER_BYTE(ABFD, SEC) 1 complain_overflow_bitfield,
NULL, "32",
false, 0xffffffff, 0xffffffff, false);
#ifndef PCRELOFFSET static const reloc_howto_type arm64_reloc_howto_32_pcrel = HOWTO (IMAGE_REL_ARM64_REL32, 0, 4, 32, true, 0,
#define PCRELOFFSET true complain_overflow_bitfield,
#endif NULL, "DISP32",
false, 0xffffffff, 0xffffffff, true);
/* Currently we don't handle any relocations. */ static const reloc_howto_type arm64_reloc_howto_branch26 = HOWTO (IMAGE_REL_ARM64_BRANCH26, 0, 4, 26, true, 0,
static reloc_howto_type pe_aarch64_std_reloc_howto[] = 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_DEFAULT_SECTION_ALIGNMENT_POWER 2
#define COFF_PAGE_SIZE 0x1000
#ifndef NUM_ELEM #ifndef NUM_ELEM
#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0])) #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
#endif #endif
#define NUM_RELOCS NUM_ELEM (pe_aarch64_std_reloc_howto) #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
#define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup
#define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup
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
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 RTYPE2HOWTO(cache_ptr, dst) \ #define RTYPE2HOWTO(cache_ptr, dst) \
(cache_ptr)->howto = NULL ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
#define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
#ifndef bfd_pe_print_pdata #ifndef bfd_pe_print_pdata
#define bfd_pe_print_pdata NULL #define bfd_pe_print_pdata NULL
@ -93,13 +209,13 @@ const bfd_target
#ifdef TARGET_SYM #ifdef TARGET_SYM
TARGET_SYM = TARGET_SYM =
#else #else
aarch64_pei_vec = # error "target symbol name not specified"
#endif #endif
{ {
#ifdef TARGET_NAME #ifdef TARGET_NAME
TARGET_NAME, TARGET_NAME,
#else #else
"pei-aarch64-little", /* Name. */ # error "target name not specified"
#endif #endif
bfd_target_coff_flavour, bfd_target_coff_flavour,
BFD_ENDIAN_LITTLE, /* Data byte order is little. */ BFD_ENDIAN_LITTLE, /* Data byte order is little. */

View File

@ -245,9 +245,15 @@ case "${targ}" in
;; ;;
aarch64-*-elf | aarch64-*-rtems* | aarch64-*-genode*) aarch64-*-elf | aarch64-*-rtems* | aarch64-*-genode*)
targ_defvec=aarch64_elf64_le_vec 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 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) aarch64_be-*-elf)
targ_defvec=aarch64_elf64_be_vec 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" 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*) aarch64-*-linux* | aarch64-*-netbsd*)
targ_defvec=aarch64_elf64_le_vec 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 want64=true
;; ;;
aarch64_be-*-linux* | aarch64_be-*-netbsd*) aarch64_be-*-linux* | aarch64_be-*-netbsd*)
@ -1488,6 +1494,12 @@ case "${targ}" in
;; ;;
esac 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. # All MIPS ELF targets need a 64-bit bfd_vma.
case "${targ_defvec} ${targ_selvecs}" in case "${targ_defvec} ${targ_selvecs}" in
*mips_elf*) *mips_elf*)

3
bfd/configure vendored
View File

@ -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_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_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_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_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_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 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;

View File

@ -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_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_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_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_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_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 ;; alpha_elf64_fbsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;

View File

@ -39,8 +39,8 @@ compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
if (a->mach == b->mach) if (a->mach == b->mach)
return a; return a;
/* Don't allow mixing ilp32 with lp64. */ /* Don't allow mixing data models. */
if ((a->mach & bfd_mach_aarch64_ilp32) != (b->mach & bfd_mach_aarch64_ilp32)) if ((a->mach ^ b->mach) & (bfd_mach_aarch64_ilp32 | bfd_mach_aarch64_llp64))
return NULL; return NULL;
/* Otherwise if either a or b is the 'default' machine /* 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; return false;
} }
#define N(NUMBER, PRINT, WORDSIZE, DEFAULT, NEXT) \ /* Figure out if llp64 is default */
{ WORDSIZE, WORDSIZE, 8, bfd_arch_aarch64, NUMBER, \ #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
#define N(NUMBER, PRINT, WORDSIZE, ADDRSIZE, DEFAULT, NEXT) \
{ WORDSIZE, ADDRSIZE, 8, bfd_arch_aarch64, NUMBER, \
"aarch64", PRINT, 4, DEFAULT, compatible, scan, \ "aarch64", PRINT, 4, DEFAULT, compatible, scan, \
bfd_arch_default_fill, NEXT, 0 } bfd_arch_default_fill, NEXT, 0 }
static const bfd_arch_info_type bfd_aarch64_arch_v8_r = static const bfd_arch_info_type bfd_aarch64_arch_v8_r =
N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, false, NULL); N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, 64, false, NULL);
static const bfd_arch_info_type bfd_aarch64_arch_ilp32 = 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); &bfd_aarch64_arch_v8_r);
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 = const bfd_arch_info_type bfd_aarch64_arch =
N (0, "aarch64", 64, true, &bfd_aarch64_arch_ilp32); N (0, "aarch64", 64, 64, AARCH64_DEFAULT, &bfd_aarch64_arch_llp64);
bool bool
bfd_is_aarch64_special_symbol_name (const char *name, int type) bfd_is_aarch64_special_symbol_name (const char *name, int type)

74
bfd/pe-aarch64.c Normal file
View File

@ -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"

View File

@ -21,7 +21,7 @@
#include "sysdep.h" #include "sysdep.h"
#include "bfd.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_NAME "pei-aarch64-little"
#define TARGET_ARCHITECTURE bfd_arch_aarch64 #define TARGET_ARCHITECTURE bfd_arch_aarch64
#define TARGET_PAGESIZE 4096 #define TARGET_PAGESIZE 4096

View File

@ -191,6 +191,8 @@ coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
#ifdef COFF_IMAGE_WITH_PE #ifdef COFF_IMAGE_WITH_PE
# define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out # 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 #elif defined COFF_WITH_pex64
# define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out # define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
#elif defined COFF_WITH_pep #elif defined COFF_WITH_pep

View File

@ -313,6 +313,7 @@ osf-core.c
pc532-mach.c pc532-mach.c
pdb.c pdb.c
pdp11.c pdp11.c
pe-aarch64.c
pe-arm-wince.c pe-arm-wince.c
pe-arm.c pe-arm.c
pe-i386.c pe-i386.c

View File

@ -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_vec;
extern const bfd_target aarch64_elf64_le_cloudabi_vec; extern const bfd_target aarch64_elf64_le_cloudabi_vec;
extern const bfd_target aarch64_mach_o_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_ecoff_le_vec;
extern const bfd_target alpha_elf64_vec; extern const bfd_target alpha_elf64_vec;
extern const bfd_target alpha_elf64_fbsd_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_vec,
&aarch64_elf64_le_cloudabi_vec, &aarch64_elf64_le_cloudabi_vec,
&aarch64_mach_o_vec, &aarch64_mach_o_vec,
&aarch64_pei_vec, &aarch64_pe_le_vec,
&aarch64_pei_le_vec,
#endif #endif
#ifdef BFD64 #ifdef BFD64

View File

@ -40,6 +40,10 @@
#endif #endif
#endif #endif
#ifdef TC_AARCH64
#include "coff/aarch64.h"
#endif
#ifdef TC_PPC #ifdef TC_PPC
#include "coff/rs6000.h" #include "coff/rs6000.h"
#endif #endif

View File

@ -30,9 +30,9 @@
#ifdef OBJ_ELF #ifdef OBJ_ELF
#include "elf/aarch64.h" #include "elf/aarch64.h"
#include "dw2gencfi.h"
#endif #endif
#include "dw2gencfi.h"
#include "dwarf2dbg.h" #include "dwarf2dbg.h"
/* Types of processor to assemble for. */ /* Types of processor to assemble for. */
@ -61,21 +61,25 @@ static aarch64_instr_sequence *insn_sequence = NULL;
#ifdef OBJ_ELF #ifdef OBJ_ELF
/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
static symbolS *GOT_symbol; static symbolS *GOT_symbol;
#endif
/* Which ABI to use. */ /* Which ABI to use. */
enum aarch64_abi_type enum aarch64_abi_type
{ {
AARCH64_ABI_NONE = 0, AARCH64_ABI_NONE = 0,
AARCH64_ABI_LP64 = 1, AARCH64_ABI_LP64 = 1,
AARCH64_ABI_ILP32 = 2 AARCH64_ABI_ILP32 = 2,
AARCH64_ABI_LLP64 = 3
}; };
#ifndef DEFAULT_ARCH #ifndef DEFAULT_ARCH
#define DEFAULT_ARCH "aarch64" #define DEFAULT_ARCH "aarch64"
#endif #endif
#ifdef OBJ_ELF
/* DEFAULT_ARCH is initialized in gas/configure.tgt. */ /* DEFAULT_ARCH is initialized in gas/configure.tgt. */
static const char *default_arch = DEFAULT_ARCH; static const char *default_arch = DEFAULT_ARCH;
#endif
/* AArch64 ABI for the output file. */ /* AArch64 ABI for the output file. */
static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_NONE; 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 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). */ and all pointer types are 64-bit objects (LP64). */
#define ilp32_p (aarch64_abi == AARCH64_ABI_ILP32) #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 enum vector_el_type
{ {
@ -1459,7 +1466,7 @@ s_unreq (int a ATTRIBUTE_UNUSED)
/* Directives: Instruction set selection. */ /* 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 /* 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). 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), 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); fix = bytes & (noop_size - 1);
if (fix) if (fix)
{ {
#ifdef OBJ_ELF #if defined OBJ_ELF || defined OBJ_COFF
insert_data_mapping_symbol (MAP_INSN, fragP->fr_fix, fragP, fix); insert_data_mapping_symbol (MAP_INSN, fragP->fr_fix, fragP, fix);
#endif #endif
memset (p, 0, fix); memset (p, 0, fix);
@ -8394,6 +8401,7 @@ aarch64_init_frag (fragS * fragP, int max_chars)
break; break;
} }
} }
#endif /* OBJ_ELF */
/* Initialize the DWARF-2 unwind information for this procedure. */ /* 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); cfi_add_CFA_def_cfa (REG_SP, 0);
} }
#endif /* OBJ_ELF */
/* Convert REGNAME to a DWARF-2 register number. */ /* Convert REGNAME to a DWARF-2 register number. */
@ -8439,10 +8446,10 @@ tc_aarch64_regname_to_dw2regnum (char *regname)
int int
aarch64_dwarf2_addr_size (void) aarch64_dwarf2_addr_size (void)
{ {
#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
if (ilp32_p) if (ilp32_p)
return 4; return 4;
#endif else if (llp64_p)
return 8;
return bfd_arch_bits_per_address (stdoutput) / 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); 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 /* 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. */ 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) if (aarch64_abi != AARCH64_ABI_NONE)
return; return;
#ifdef OBJ_ELF
/* DEFAULT_ARCH will have ":32" extension if it's configured for ILP32. */ /* DEFAULT_ARCH will have ":32" extension if it's configured for ILP32. */
if (strlen (default_arch) > 7 && strcmp (default_arch + 7, ":32") == 0) if (strlen (default_arch) > 7 && strcmp (default_arch + 7, ":32") == 0)
aarch64_abi = AARCH64_ABI_ILP32; aarch64_abi = AARCH64_ABI_ILP32;
else else
aarch64_abi = AARCH64_ABI_LP64; aarch64_abi = AARCH64_ABI_LP64;
#else
aarch64_abi = AARCH64_ABI_LLP64;
#endif
} }
#ifdef OBJ_ELF
const char * const char *
elf64_aarch64_target_format (void) elf64_aarch64_target_format (void)
{ {
@ -9347,6 +9357,12 @@ aarch64elf_frob_symbol (symbolS * symp, int *puntp)
{ {
elf_frob_symbol (symp, puntp); elf_frob_symbol (symp, puntp);
} }
#elif defined OBJ_COFF
const char *
coff_aarch64_target_format (void)
{
return "pe-aarch64-little";
}
#endif #endif
/* MD interface: Finalization. */ /* MD interface: Finalization. */
@ -9662,7 +9678,12 @@ md_begin (void)
cpu_variant = *mcpu_cpu_opt; cpu_variant = *mcpu_cpu_opt;
/* Record the CPU type. */ /* 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); 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[] = { static const struct aarch64_option_abi_value_table aarch64_abis[] = {
#ifdef OBJ_ELF
{"ilp32", AARCH64_ABI_ILP32}, {"ilp32", AARCH64_ABI_ILP32},
{"lp64", AARCH64_ABI_LP64}, {"lp64", AARCH64_ABI_LP64},
#else
{"llp64", AARCH64_ABI_LLP64},
#endif
}; };
static int static int
@ -10257,10 +10282,8 @@ aarch64_parse_abi (const char *str)
} }
static struct aarch64_long_option_table aarch64_long_opts[] = { static struct aarch64_long_option_table aarch64_long_opts[] = {
#ifdef OBJ_ELF
{"mabi=", N_("<abi name>\t specify for ABI <abi name>"), {"mabi=", N_("<abi name>\t specify for ABI <abi name>"),
aarch64_parse_abi, NULL}, aarch64_parse_abi, NULL},
#endif /* OBJ_ELF */
{"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"), {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
aarch64_parse_cpu, NULL}, aarch64_parse_cpu, NULL},
{"march=", N_("<arch name>\t assemble for architecture <arch name>"), {"march=", N_("<arch name>\t assemble for architecture <arch name>"),

View File

@ -59,9 +59,11 @@ struct aarch64_fix
enum aarch64_opnd opnd; enum aarch64_opnd opnd;
}; };
#if defined OBJ_ELF #ifdef OBJ_ELF
# define AARCH64_BI_ENDIAN # define AARCH64_BI_ENDIAN
# define TARGET_FORMAT elf64_aarch64_target_format () # define TARGET_FORMAT elf64_aarch64_target_format ()
#elif defined (OBJ_COFF)
# define TARGET_FORMAT coff_aarch64_target_format ()
#endif #endif
#define TC_FORCE_RELOCATION(FIX) aarch64_force_relocation (FIX) #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 struct aarch64_frag_type
{ {
int recorded; int recorded;
#ifdef OBJ_ELF #if defined OBJ_ELF || defined OBJ_COFF
/* If there is a mapping symbol at offset 0 in this frag, /* If there is a mapping symbol at offset 0 in this frag,
it will be saved in FIRST_MAP. If there are any mapping it will be saved in FIRST_MAP. If there are any mapping
symbols in this frag, the last one will be saved in 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); extern int aarch64_dwarf2_addr_size (void);
#define DWARF2_ADDR_SIZE(bfd) aarch64_dwarf2_addr_size () #define DWARF2_ADDR_SIZE(bfd) aarch64_dwarf2_addr_size ()
#if defined OBJ_ELF || defined OBJ_COFF
#ifdef OBJ_ELF #ifdef OBJ_ELF
# define obj_frob_symbol(sym, punt) aarch64elf_frob_symbol ((sym), & (punt)) # define obj_frob_symbol(sym, punt) aarch64elf_frob_symbol ((sym), & (punt))
#endif
# define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" # define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
# define TC_SEGMENT_INFO_TYPE struct aarch64_segment_info_type # 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 void aarch64_frag_align_code (int, int);
extern const char * elf64_aarch64_target_format (void); extern const char * elf64_aarch64_target_format (void);
extern const char * coff_aarch64_target_format (void);
extern int aarch64_force_relocation (struct fix *); extern int aarch64_force_relocation (struct fix *);
extern void aarch64_cleanup (void); extern void aarch64_cleanup (void);
extern void aarch64_start_line_hook (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 int tc_aarch64_regname_to_dw2regnum (char *regname);
extern void tc_aarch64_frame_initial_instructions (void); 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 */ #endif /* TC_AARCH64 */

View File

@ -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"

View File

@ -135,7 +135,7 @@ case ${generic_target} in
esac ;; esac ;;
aarch64*-*-netbsd*) fmt=elf em=nbsd;; aarch64*-*-netbsd*) fmt=elf em=nbsd;;
aarch64*-*-openbsd*) fmt=elf;; aarch64*-*-openbsd*) fmt=elf;;
aarch64*-*-pe*) fmt=coff em=pepaarch64 ;;
alpha-*-*vms*) fmt=evax ;; alpha-*-*vms*) fmt=evax ;;
alpha-*-osf*) fmt=ecoff ;; alpha-*-osf*) fmt=ecoff ;;
alpha-*-linux*ecoff*) fmt=ecoff ;; alpha-*-linux*ecoff*) fmt=ecoff ;;

View File

@ -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 <foo>
0000000000000008 <foo>:
8: d65f03c0 ret

View File

@ -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

View File

@ -52,6 +52,12 @@ if ([istarget "x86_64-*-mingw*"]) then {
run_dump_test "peseh-x64-6" run_dump_test "peseh-x64-6"
} }
# This test is only for AArch64
if ([istarget "aarch64-*-pe*"]) {
run_dump_test "pe-aarch64"
}
# Big obj # Big obj

View File

@ -331,7 +331,9 @@ read_pe_exported_syms (minimal_symbol_reader &reader,
section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
is_pe64 = (strcmp (target, "pe-x86-64") == 0 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 is_pe32 = (strcmp (target, "pe-i386") == 0
|| strcmp (target, "pei-i386") == 0 || strcmp (target, "pei-i386") == 0
|| strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pe-arm-wince-little") == 0
@ -610,7 +612,9 @@ pe_text_section_offset (struct bfd *abfd)
target = bfd_get_target (abfd); target = bfd_get_target (abfd);
is_pe64 = (strcmp (target, "pe-x86-64") == 0 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 is_pe32 = (strcmp (target, "pe-i386") == 0
|| strcmp (target, "pei-i386") == 0 || strcmp (target, "pei-i386") == 0
|| strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pe-arm-wince-little") == 0

View File

@ -60,4 +60,26 @@ struct external_reloc
#define RELOC struct external_reloc #define RELOC struct external_reloc
#define RELSZ 14 #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" #define ARM_NOTE_SECTION ".note"

View File

@ -377,6 +377,7 @@ ALL_EMULATIONS = $(ALL_EMULATION_SOURCES:.c=.@OBJEXT@)
ALL_64_EMULATION_SOURCES = \ ALL_64_EMULATION_SOURCES = \
eaarch64cloudabi.c \ eaarch64cloudabi.c \
eaarch64cloudabib.c \ eaarch64cloudabib.c \
eaarch64pe.c \
eaarch64elf.c \ eaarch64elf.c \
eaarch64elf32.c \ eaarch64elf32.c \
eaarch64elf32b.c \ eaarch64elf32b.c \

View File

@ -887,6 +887,7 @@ ALL_64_EMULATION_SOURCES = \
eaarch64linux32.c \ eaarch64linux32.c \
eaarch64linux32b.c \ eaarch64linux32b.c \
eaarch64linuxb.c \ eaarch64linuxb.c \
eaarch64pe.c \
eelf32_x86_64.c \ eelf32_x86_64.c \
eelf32b4300.c \ eelf32b4300.c \
eelf32bmip.c \ eelf32bmip.c \

View File

@ -117,6 +117,10 @@ aarch64-*-linux*) targ_emul=aarch64linux
aarch64-*-haiku*) targ_emul=aarch64haiku aarch64-*-haiku*) targ_emul=aarch64haiku
targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b aarch64elfb armelf armelfb armelf_haiku $targ_extra_libpath" 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) alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
targ_emul=elf64alpha_fbsd targ_emul=elf64alpha_fbsd
targ_extra_emuls="elf64alpha alpha" 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 ; x86_64-*-pe | x86_64-*-pep) targ_emul=i386pep ;
targ_extra_emuls=i386pe ; 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 ; x86_64-*-cygwin) targ_emul=i386pep ;
targ_extra_emuls=i386pe targ_extra_emuls=i386pe

View File

@ -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

View File

@ -48,7 +48,11 @@ fragment <<EOF
#define COFF_IMAGE_WITH_PE #define COFF_IMAGE_WITH_PE
#define COFF_WITH_PE #define COFF_WITH_PE
#ifdef TARGET_IS_aarch64pe
#define COFF_WITH_peAArch64
#elif defined (TARGET_IS_i386pep)
#define COFF_WITH_pex64 #define COFF_WITH_pex64
#endif
#include "sysdep.h" #include "sysdep.h"
#include "bfd.h" #include "bfd.h"
@ -72,7 +76,11 @@ fragment <<EOF
/* FIXME: See bfd/peXXigen.c for why we include an architecture specific /* FIXME: See bfd/peXXigen.c for why we include an architecture specific
header in generic PE code. */ header in generic PE code. */
#ifdef TARGET_IS_i386pep
# include "coff/x86_64.h" # include "coff/x86_64.h"
#elif defined TARGET_IS_aarch64pe
# include "coff/aarch64.h"
#endif
#include "coff/pe.h" #include "coff/pe.h"
/* FIXME: These are BFD internal header files, and we should not be /* FIXME: These are BFD internal header files, and we should not be

View File

@ -42,7 +42,7 @@
#include "../bfd/libcoff.h" #include "../bfd/libcoff.h"
#include "deffile.h" #include "deffile.h"
#ifdef pe_use_x86_64 #ifdef pe_use_plus
#define PE_IDATA4_SIZE 8 #define PE_IDATA4_SIZE 8
#define PE_IDATA5_SIZE 8 #define PE_IDATA5_SIZE 8
@ -209,7 +209,7 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
{ STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") }, { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") },
/* Entry point symbols, and entry hooks. */ /* Entry point symbols, and entry hooks. */
{ STRING_COMMA_LEN ("cygwin_crt0") }, { STRING_COMMA_LEN ("cygwin_crt0") },
#ifdef pe_use_x86_64 #ifdef pe_use_plus
{ STRING_COMMA_LEN ("DllMain") }, { STRING_COMMA_LEN ("DllMain") },
{ STRING_COMMA_LEN ("DllEntryPoint") }, { STRING_COMMA_LEN ("DllEntryPoint") },
{ STRING_COMMA_LEN ("DllMainCRTStartup") }, { STRING_COMMA_LEN ("DllMainCRTStartup") },
@ -246,13 +246,14 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
#define PE_ARCH_mips 3 #define PE_ARCH_mips 3
#define PE_ARCH_arm 4 #define PE_ARCH_arm 4
#define PE_ARCH_arm_wince 5 #define PE_ARCH_arm_wince 5
#define PE_ARCH_aarch64 6
/* Don't make it constant as underscore mode gets possibly overriden /* Don't make it constant as underscore mode gets possibly overriden
by target or -(no-)leading-underscore option. */ by target or -(no-)leading-underscore option. */
static pe_details_type pe_detail_list[] = static pe_details_type pe_detail_list[] =
{ {
{ {
#ifdef pe_use_x86_64 #ifdef pe_use_plus
"pei-x86-64", "pei-x86-64",
"pe-x86-64", "pe-x86-64",
3 /* R_IMAGEBASE */, 3 /* R_IMAGEBASE */,
@ -263,14 +264,14 @@ static pe_details_type pe_detail_list[] =
#endif #endif
PE_ARCH_i386, PE_ARCH_i386,
bfd_arch_i386, bfd_arch_i386,
#ifdef pe_use_x86_64 #ifdef pe_use_plus
false, false,
#else #else
true, true,
#endif #endif
autofilter_symbollist_i386 autofilter_symbollist_i386
}, },
#ifdef pe_use_x86_64 #ifdef pe_use_plus
{ {
"pei-x86-64", "pei-x86-64",
"pe-bigobj-x86-64", "pe-bigobj-x86-64",
@ -327,6 +328,15 @@ static pe_details_type pe_detail_list[] =
false, false,
autofilter_symbollist_generic autofilter_symbollist_generic
}, },
{
"pei-aarch64-little",
"pe-aarch64-little",
2, /* ARM64_RVA32 */
PE_ARCH_aarch64,
bfd_arch_aarch64,
false,
autofilter_symbollist_generic
},
{ NULL, NULL, 0, 0, 0, false, NULL } { NULL, NULL, 0, 0, 0, false, NULL }
}; };
@ -1638,7 +1648,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
switch BITS_AND_SHIFT (relocs[i]->howto->bitsize, switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
relocs[i]->howto->rightshift) relocs[i]->howto->rightshift)
{ {
#ifdef pe_use_x86_64 #ifdef pe_use_plus
case BITS_AND_SHIFT (64, 0): case BITS_AND_SHIFT (64, 0):
reloc_data[total_relocs].type = IMAGE_REL_BASED_DIR64; reloc_data[total_relocs].type = IMAGE_REL_BASED_DIR64;
total_relocs++; total_relocs++;
@ -2247,6 +2257,15 @@ static const unsigned char jmp_ix86_bytes[] =
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 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: /* _function:
mov.l ip+8,r0 mov.l ip+8,r0
mov.l @r0,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_bytes = jmp_arm_bytes;
jmp_byte_count = sizeof (jmp_arm_bytes); jmp_byte_count = sizeof (jmp_arm_bytes);
break; break;
case PE_ARCH_aarch64:
jmp_bytes = jmp_aarch64_bytes;
jmp_byte_count = sizeof (jmp_aarch64_bytes);
break;
default: default:
abort (); abort ();
} }
@ -2386,7 +2409,7 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
switch (pe_details->pe_arch) switch (pe_details->pe_arch)
{ {
case PE_ARCH_i386: case PE_ARCH_i386:
#ifdef pe_use_x86_64 #ifdef pe_use_plus
quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2); quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
#else #else
/* Mark this object as SAFESEH compatible. */ /* 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: case PE_ARCH_arm_wince:
quick_reloc (abfd, 8, BFD_RELOC_32, 2); quick_reloc (abfd, 8, BFD_RELOC_32, 2);
break; break;
case PE_ARCH_aarch64:
quick_reloc (abfd, 0, BFD_RELOC_AARCH64_JUMP26, 2);
break;
default: default:
abort (); abort ();
} }
@ -3406,7 +3432,7 @@ pe_implied_import_dll (const char *filename)
/* Get pe_header, optional header and numbers of directory entries. */ /* Get pe_header, optional header and numbers of directory entries. */
pe_header_offset = pe_get32 (dll, 0x3c); pe_header_offset = pe_get32 (dll, 0x3c);
opthdr_ofs = pe_header_offset + 4 + 20; 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. */ num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */
#else #else
num_entries = pe_get32 (dll, opthdr_ofs + 92); num_entries = pe_get32 (dll, opthdr_ofs + 92);
@ -3416,7 +3442,7 @@ pe_implied_import_dll (const char *filename)
if (num_entries < 1) if (num_entries < 1)
return false; return false;
#ifdef pe_use_x86_64 #ifdef pe_use_plus
export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4); export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4);
export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4); export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4);
#else #else

23
ld/pep-dll-aarch64.c Normal file
View File

@ -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"

22
ld/pep-dll-x86_64.c Normal file
View File

@ -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"

View File

@ -21,7 +21,6 @@
#define COFF_IMAGE_WITH_PE #define COFF_IMAGE_WITH_PE
#define COFF_WITH_PE #define COFF_WITH_PE
#define COFF_WITH_pex64
/* Local defined globals. */ /* Local defined globals. */
#define pe_def_file pep_def_file #define pe_def_file pep_def_file
@ -58,7 +57,7 @@
#define pe_output_file_set_long_section_names \ #define pe_output_file_set_long_section_names \
pep_output_file_set_long_section_names pep_output_file_set_long_section_names
/* Uses x86_64 PE+. */ /* Uses PE+. */
#define pe_use_x86_64 #define pe_use_plus
#include "pe-dll.c" #include "pe-dll.c"

View File

@ -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 <foo>
0000000140001008 <foo>:
140001008: d65f03c0 ret
14000100c: 00000000 udf #0
#...

View File

@ -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

View File

@ -78,6 +78,11 @@ if {[istarget i*86-*-cygwin*]
run_ld_link_tests $pe_tests run_ld_link_tests $pe_tests
} }
if {[istarget "aarch64-*-pe*"]} {
run_dump_test "pe-aarch64"
}
run_dump_test "image_size" run_dump_test "image_size"
run_dump_test "export_dynamic_warning" run_dump_test "export_dynamic_warning"