diff options
author | Jedidiah Thompson <wej22007@outlook.com> | 2022-10-19 10:57:12 +0200 |
---|---|---|
committer | Zac Walker <zac.walker@linaro.org> | 2022-10-19 10:57:12 +0200 |
commit | c60b3806799abf1d7f6cf5108a1b0e733a950b13 (patch) | |
tree | a203af8ed31ff48618e57a76a668faea3673fb0e /ld | |
parent | 740a19d914a83423122fe81eec9508fa1dbb0559 (diff) | |
download | gdb-c60b3806799abf1d7f6cf5108a1b0e733a950b13.zip gdb-c60b3806799abf1d7f6cf5108a1b0e733a950b13.tar.gz gdb-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.am | 1 | ||||
-rw-r--r-- | ld/Makefile.in | 1 | ||||
-rw-r--r-- | ld/configure.tgt | 6 | ||||
-rw-r--r-- | ld/emulparams/aarch64pe.sh | 9 | ||||
-rw-r--r-- | ld/emultempl/pep.em | 10 | ||||
-rw-r--r-- | ld/pe-dll.c | 44 | ||||
-rw-r--r-- | ld/pep-dll-aarch64.c | 23 | ||||
-rw-r--r-- | ld/pep-dll-x86_64.c | 22 | ||||
-rw-r--r-- | ld/pep-dll.c | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pe-aarch64.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pe-aarch64.s | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pe.exp | 5 |
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" |