From 16fea92ccd993fce6b5b0efebe059d542cad9932 Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Thu, 5 Jan 2023 02:36:32 +0000 Subject: [PATCH] Add aarch64-w64-mingw32 target This adds a mingw target for aarch64, including windres and dlltool. Note that the old value of jmp_aarch64_bytes was wrong, and this does the same thing as MSVC does. --- bfd/config.bfd | 4 +-- bfd/peicode.h | 2 +- binutils/configure | 10 ++++++ binutils/configure.ac | 10 ++++++ binutils/dlltool.c | 57 +++++++++++++++++++++++++++++--- binutils/rescoff.c | 3 ++ gas/configure.tgt | 2 +- gas/testsuite/gas/pe/pe.exp | 2 +- ld/configure.tgt | 4 +-- ld/emultempl/pep.em | 11 +++--- ld/pe-dll.c | 12 +++---- ld/testsuite/ld-pe/pe-aarch64.d | 13 ++++++-- ld/testsuite/ld-pe/pe.exp | 2 +- ld/testsuite/ld-scripts/weak.exp | 1 + 14 files changed, 109 insertions(+), 24 deletions(-) diff --git a/bfd/config.bfd b/bfd/config.bfd index 800afa8105f..0b0f7d50602 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -247,9 +247,9 @@ case "${targ}" in 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*) + aarch64-*-pe* | aarch64-*-mingw*) targ_defvec=aarch64_pe_le_vec - targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec" + targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec aarch64_elf64_le_vec aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec pdb_vec" want64=true targ_underscore=no ;; diff --git a/bfd/peicode.h b/bfd/peicode.h index 06642c3db5a..68ec3a37c89 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -444,7 +444,7 @@ pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) #define SIZEOF_IDATA2 (5 * 4) /* For PEx64 idata4 & 5 have thumb size of 8 bytes. */ -#ifdef COFF_WITH_pex64 +#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) #define SIZEOF_IDATA4 (2 * 4) #define SIZEOF_IDATA5 (2 * 4) #else diff --git a/binutils/configure b/binutils/configure index 20fd420dbaa..f27ee48be73 100755 --- a/binutils/configure +++ b/binutils/configure @@ -14578,6 +14578,16 @@ do esac case $targ in + aarch64-*-mingw*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + if test -z "$DLLTOOL_DEFAULT"; then + DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_AARCH64" + fi + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_AARCH64" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' + BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' + ;; arm-wince-pe* | arm-*-wince | arm*-*-cegcc* | arm*-*-mingw32ce*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' if test -z "$DLLTOOL_DEFAULT"; then diff --git a/binutils/configure.ac b/binutils/configure.ac index a217c81858f..dc93ac1f390 100644 --- a/binutils/configure.ac +++ b/binutils/configure.ac @@ -355,6 +355,16 @@ do esac case $targ in + aarch64-*-mingw*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + if test -z "$DLLTOOL_DEFAULT"; then + DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_AARCH64" + fi + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_AARCH64" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' + BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' + ;; arm-wince-pe* | arm-*-wince | arm*-*-cegcc* | arm*-*-mingw32ce*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' if test -z "$DLLTOOL_DEFAULT"; then diff --git a/binutils/dlltool.c b/binutils/dlltool.c index 7ca6906e2bd..31c864d7d5c 100644 --- a/binutils/dlltool.c +++ b/binutils/dlltool.c @@ -442,6 +442,11 @@ static const char *mname = "arm"; static const char *mname = "arm-wince"; #endif +#ifdef DLLTOOL_DEFAULT_AARCH64 +/* arm64 rather than aarch64 to match llvm-dlltool */ +static const char *mname = "arm64"; +#endif + #ifdef DLLTOOL_DEFAULT_I386 static const char *mname = "i386"; #endif @@ -560,6 +565,14 @@ static const unsigned char mcore_le_jtab[] = 0x00, 0x00, 0x00, 0x00 /*
*/ }; +static const unsigned char aarch64_jtab[] = +{ + 0x10, 0x00, 0x00, 0x90, /* adrp x16, 0 */ + 0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */ + 0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16] */ + 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ +}; + static const char i386_trampoline[] = "\tpushl %%ecx\n" "\tpushl %%edx\n" @@ -717,6 +730,15 @@ mtable[] = i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, true, i386_x64_trampoline } , + { +#define MAARCH64 10 + "arm64", ".byte", ".short", ".long", ".asciz", "//", + "bl ", ".global", ".space", ".balign\t2", ".balign\t4", "", + "pe-aarch64-little", bfd_arch_aarch64, + aarch64_jtab, sizeof (aarch64_jtab), 0, + 0, 0, 0, 0, 0, false, 0 + } + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -864,6 +886,7 @@ rvaafter (int mach) case MMCORE_ELF: case MMCORE_ELF_LE: case MARM_WINCE: + case MAARCH64: break; default: /* xgettext:c-format */ @@ -888,6 +911,7 @@ rvabefore (int mach) case MMCORE_ELF: case MMCORE_ELF_LE: case MARM_WINCE: + case MAARCH64: return ".rva\t"; default: /* xgettext:c-format */ @@ -910,6 +934,7 @@ asm_prefix (int mach, const char *name) case MMCORE_ELF: case MMCORE_ELF_LE: case MARM_WINCE: + case MAARCH64: break; case M386: case MX86: @@ -2474,6 +2499,8 @@ make_one_lib_file (export_type *exp, int i, int delay) case TEXT: if (! exp->data) { + unsigned int rpp_len; + si->size = HOW_JTAB_SIZE; si->data = xmalloc (HOW_JTAB_SIZE); memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); @@ -2481,7 +2508,12 @@ make_one_lib_file (export_type *exp, int i, int delay) /* Add the reloc into idata$5. */ rel = xmalloc (sizeof (arelent)); - rpp = xmalloc (sizeof (arelent *) * (delay ? 4 : 2)); + rpp_len = delay ? 4 : 2; + + if (machine == MAARCH64) + rpp_len++; + + rpp = xmalloc (sizeof (arelent *) * rpp_len); rpp[0] = rel; rpp[1] = 0; @@ -2507,6 +2539,22 @@ make_one_lib_file (export_type *exp, int i, int delay) BFD_RELOC_32_PCREL); rel->sym_ptr_ptr = iname_pp; } + else if (machine == MAARCH64) + { + arelent *rel_add; + + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL); + rel->sym_ptr_ptr = secdata[IDATA5].sympp; + + rel_add = xmalloc (sizeof (arelent)); + rel_add->address = 4; + rel_add->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADD_LO12); + rel_add->sym_ptr_ptr = secdata[IDATA5].sympp; + rel_add->addend = 0; + + rpp[rpp_len - 2] = rel_add; + rpp[rpp_len - 1] = 0; + } else { rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); @@ -2527,7 +2575,7 @@ make_one_lib_file (export_type *exp, int i, int delay) } sec->orelocation = rpp; - sec->reloc_count = delay ? 3 : 1; + sec->reloc_count = rpp_len - 1; } break; @@ -3674,7 +3722,7 @@ usage (FILE *file, int status) fprintf (file, _("Usage %s \n"), program_name); /* xgetext:c-format */ fprintf (file, _(" -m --machine Create as DLL for . [default: %s]\n"), mname); - fprintf (file, _(" possible : arm[_interwork], i386, mcore[-elf]{-le|-be}, thumb\n")); + fprintf (file, _(" possible : arm[_interwork], arm64, i386, mcore[-elf]{-le|-be}, thumb\n")); fprintf (file, _(" -e --output-exp Generate an export file.\n")); fprintf (file, _(" -l --output-lib Generate an interface library.\n")); fprintf (file, _(" -y --output-delaylib Create a delay-import library.\n")); @@ -3967,7 +4015,8 @@ main (int ac, char **av) machine = i; /* Check if we generated PE+. */ - create_for_pep = strcmp (mname, "i386:x86-64") == 0; + create_for_pep = strcmp (mname, "i386:x86-64") == 0 || + strcmp (mname, "arm64") == 0; { /* Check the default underscore */ diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 1fb6bf41105..40a8f452a1f 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -463,6 +463,9 @@ write_coff_file (const char *filename, const char *target, #elif defined DLLTOOL_ARM if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0)) bfd_fatal ("bfd_set_arch_mach(arm)"); +#elif defined DLLTOOL_AARCH64 + if (! bfd_set_arch_mach (abfd, bfd_arch_aarch64, 0)) + bfd_fatal ("bfd_set_arch_mach(aarch64)"); #else /* FIXME: This is obviously i386 specific. */ if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0)) diff --git a/gas/configure.tgt b/gas/configure.tgt index c210845d567..b7a1874781f 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 ;; + aarch64*-*-pe* | aarch64*-*-mingw*) 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.exp b/gas/testsuite/gas/pe/pe.exp index a1bb4bc6a11..172bc3caf6e 100644 --- a/gas/testsuite/gas/pe/pe.exp +++ b/gas/testsuite/gas/pe/pe.exp @@ -54,7 +54,7 @@ if ([istarget "x86_64-*-mingw*"]) then { # This test is only for AArch64 -if ([istarget "aarch64-*-pe*"]) { +if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} { run_dump_test "pe-aarch64" } diff --git a/ld/configure.tgt b/ld/configure.tgt index aa74d2521bf..4f9a61f95ce 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -118,10 +118,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*) +aarch64-*-pe* | aarch64-*-mingw*) targ_emul=aarch64pe targ_extra_emuls="arm64pe" - targ_extra_ofiles="deffilep.o pep-dll-aarch64.o" + targ_extra_ofiles="deffilep.o pep-dll-aarch64.o pe-dll.o" ;; alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu) targ_emul=elf64alpha_fbsd diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 6ac70f9cfa4..f0e678b84ed 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -121,7 +121,7 @@ fragment <owner, addend); break; + case 26: case 32: suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4); if (suc && rel->howto->pc_relative) @@ -1577,14 +1578,14 @@ gld${EMULATION_NAME}_after_open (void) if (pep_enable_stdcall_fixup) /* -1=warn or 1=enable */ pep_fixup_stdcalls (); -#ifndef TARGET_IS_i386pep +#if !defined(TARGET_IS_i386pep) && !defined(COFF_WITH_peAArch64) if (bfd_link_pic (&link_info)) #else if (!bfd_link_relocatable (&link_info)) #endif pep_dll_build_sections (link_info.output_bfd, &link_info); -#ifndef TARGET_IS_i386pep +#if !defined(TARGET_IS_i386pep) && !defined(COFF_WITH_peAArch64) else pep_exe_build_sections (link_info.output_bfd, &link_info); #endif @@ -1880,6 +1881,8 @@ gld${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE #ifdef DLL_SUPPORT #ifdef TARGET_IS_i386pep pep_dll_id_target ("pei-x86-64"); +#elif defined(COFF_WITH_peAArch64) + pep_dll_id_target ("pei-aarch64-little"); #endif if (pep_bfd_is_dll (entry->the_bfd)) return pep_implied_import_dll (entry->filename); diff --git a/ld/pe-dll.c b/ld/pe-dll.c index de876ca5094..a2584c39d0d 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -2257,13 +2257,12 @@ 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 + 0x10, 0x00, 0x00, 0x90, /* adrp x16, 0 */ + 0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */ + 0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16] */ + 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ }; /* _function: @@ -2431,7 +2430,8 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub) quick_reloc (abfd, 8, BFD_RELOC_32, 2); break; case PE_ARCH_aarch64: - quick_reloc (abfd, 0, BFD_RELOC_AARCH64_JUMP26, 2); + quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, 2); + quick_reloc (abfd, 4, BFD_RELOC_AARCH64_ADD_LO12, 2); break; default: abort (); diff --git a/ld/testsuite/ld-pe/pe-aarch64.d b/ld/testsuite/ld-pe/pe-aarch64.d index fac02b5fd87..ab6370fb514 100644 --- a/ld/testsuite/ld-pe/pe-aarch64.d +++ b/ld/testsuite/ld-pe/pe-aarch64.d @@ -6,11 +6,20 @@ Disassembly of section .text: -0000000140001000 <__rt_psrelocs_end>: +0000000140001000 <___crt_xc_end__>: 140001000: d2800281 mov x1, #0x14 // #20 140001004: 14000001 b 140001008 0000000140001008 : 140001008: d65f03c0 ret 14000100c: 00000000 udf #0 -#... + +0000000140001010 <__CTOR_LIST__>: + 140001010: ffffffff .inst 0xffffffff ; undefined + 140001014: ffffffff .inst 0xffffffff ; undefined + ... + +0000000140001020 <__DTOR_LIST__>: + 140001020: ffffffff .inst 0xffffffff ; undefined + 140001024: ffffffff .inst 0xffffffff ; undefined + ... diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp index dae8c34066b..c4d48bb8c08 100644 --- a/ld/testsuite/ld-pe/pe.exp +++ b/ld/testsuite/ld-pe/pe.exp @@ -78,7 +78,7 @@ if {[istarget i*86-*-cygwin*] run_ld_link_tests $pe_tests } -if {[istarget "aarch64-*-pe*"]} { +if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} { run_dump_test "pe-aarch64" set pe_tests { diff --git a/ld/testsuite/ld-scripts/weak.exp b/ld/testsuite/ld-scripts/weak.exp index 78d0616a0e1..bf6f8862571 100644 --- a/ld/testsuite/ld-scripts/weak.exp +++ b/ld/testsuite/ld-scripts/weak.exp @@ -31,6 +31,7 @@ if {! [is_elf_format] && ! [is_pecoff_format]} { # Weak symbols are broken for most PE targets. if {! [istarget i?86-*-*] && ! [istarget sh-*-*]} { setup_xfail *-*-pe* + setup_xfail *-*-mingw* } # hppa64 is incredibly broken -- 2.30.2