aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorJedidiah Thompson <wej22007@outlook.com>2022-10-19 10:57:12 +0200
committerZac Walker <zac.walker@linaro.org>2022-10-19 10:57:12 +0200
commitc60b3806799abf1d7f6cf5108a1b0e733a950b13 (patch)
treea203af8ed31ff48618e57a76a668faea3673fb0e /ld
parent740a19d914a83423122fe81eec9508fa1dbb0559 (diff)
downloadbinutils-c60b3806799abf1d7f6cf5108a1b0e733a950b13.zip
binutils-c60b3806799abf1d7f6cf5108a1b0e733a950b13.tar.gz
binutils-c60b3806799abf1d7f6cf5108a1b0e733a950b13.tar.bz2
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>
Diffstat (limited to 'ld')
-rw-r--r--ld/Makefile.am1
-rw-r--r--ld/Makefile.in1
-rw-r--r--ld/configure.tgt6
-rw-r--r--ld/emulparams/aarch64pe.sh9
-rw-r--r--ld/emultempl/pep.em10
-rw-r--r--ld/pe-dll.c44
-rw-r--r--ld/pep-dll-aarch64.c23
-rw-r--r--ld/pep-dll-x86_64.c22
-rw-r--r--ld/pep-dll.c5
-rw-r--r--ld/testsuite/ld-pe/pe-aarch64.d16
-rw-r--r--ld/testsuite/ld-pe/pe-aarch64.s11
-rw-r--r--ld/testsuite/ld-pe/pe.exp5
12 files changed, 139 insertions, 14 deletions
diff --git a/ld/Makefile.am b/ld/Makefile.am
index bbe25f3..b4ec47a 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 400eed2..21d7edb 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 2bae909..9763988 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 0000000..02bf02c
--- /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 d94f18b..7a390e7 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -48,7 +48,11 @@ fragment <<EOF
#define COFF_IMAGE_WITH_PE
#define COFF_WITH_PE
+#ifdef TARGET_IS_aarch64pe
+#define COFF_WITH_peAArch64
+#elif defined (TARGET_IS_i386pep)
#define COFF_WITH_pex64
+#endif
#include "sysdep.h"
#include "bfd.h"
@@ -72,7 +76,11 @@ fragment <<EOF
/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
header in generic PE code. */
-#include "coff/x86_64.h"
+#ifdef TARGET_IS_i386pep
+# include "coff/x86_64.h"
+#elif defined TARGET_IS_aarch64pe
+# include "coff/aarch64.h"
+#endif
#include "coff/pe.h"
/* FIXME: These are BFD internal header files, and we should not be
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index 338e2de..df16e85 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -42,7 +42,7 @@
#include "../bfd/libcoff.h"
#include "deffile.h"
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
#define PE_IDATA4_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") },
/* Entry point symbols, and entry hooks. */
{ STRING_COMMA_LEN ("cygwin_crt0") },
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
{ STRING_COMMA_LEN ("DllMain") },
{ STRING_COMMA_LEN ("DllEntryPoint") },
{ STRING_COMMA_LEN ("DllMainCRTStartup") },
@@ -246,13 +246,14 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
#define PE_ARCH_mips 3
#define PE_ARCH_arm 4
#define PE_ARCH_arm_wince 5
+#define PE_ARCH_aarch64 6
/* Don't make it constant as underscore mode gets possibly overriden
by target or -(no-)leading-underscore option. */
static pe_details_type pe_detail_list[] =
{
{
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
"pei-x86-64",
"pe-x86-64",
3 /* R_IMAGEBASE */,
@@ -263,14 +264,14 @@ static pe_details_type pe_detail_list[] =
#endif
PE_ARCH_i386,
bfd_arch_i386,
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
false,
#else
true,
#endif
autofilter_symbollist_i386
},
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
{
"pei-x86-64",
"pe-bigobj-x86-64",
@@ -327,6 +328,15 @@ static pe_details_type pe_detail_list[] =
false,
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 }
};
@@ -1638,7 +1648,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
switch BITS_AND_SHIFT (relocs[i]->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++;
@@ -2248,6 +2258,15 @@ static const unsigned char jmp_ix86_bytes[] =
};
/* _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
jmp @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 0000000..61c9a2a
--- /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 0000000..0be1898
--- /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 3049a02..1cfed49 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 0000000..fac02b5
--- /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 <foo>
+
+0000000140001008 <foo>:
+ 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 0000000..5d49350
--- /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 22819e0..d8595ee 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"