[5/5] Add aarch64-w64-mingw32 target

Message ID 20221216021400.22309-5-mark@harmstone.com
State Accepted
Headers
Series [1/5] Fix size of external_reloc for pe-aarch64 |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Mark Harmstone Dec. 16, 2022, 2:14 a.m. UTC
  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             | 10 +++---
 ld/pe-dll.c                     | 12 +++----
 ld/testsuite/ld-pe/pe-aarch64.d | 13 ++++++--
 ld/testsuite/ld-pe/pe.exp       |  2 +-
 13 files changed, 107 insertions(+), 24 deletions(-)
  

Comments

Jan Beulich Dec. 16, 2022, 7:28 a.m. UTC | #1
On 16.12.2022 03:14, Mark Harmstone wrote:
> --- a/bfd/config.bfd
> +++ b/bfd/config.bfd
> @@ -249,9 +249,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"
>      want64=true
>      targ_underscore=no
>      ;;

Here and elsewhere - are you really targeting a 32-bit ABI (as per the
title)? Or do you instead mean aarch64-*-mingw64, or yet more generically
aarch64-*-mingw*? (From the *-s I used you can see that I also find a
middle component "w64" odd. Luckily you use this only in the title.) The
32- vs 64-bit ABI distinction should imo be done minimally in a way
preventing later confusion, i.e. it would be fine to support just one,
but then an attempt to configure for the other should result in an error,
not in the building of tools for the other ABI. Seeing that mingw{32,64}
are only really distinguished in the top level directory, I wonder though
whether that isn't improperly separated elsewhere as well.

Jan
  
Martin Storsjö Dec. 18, 2022, 10:44 p.m. UTC | #2
On Fri, 16 Dec 2022, Jan Beulich via Binutils wrote:

> On 16.12.2022 03:14, Mark Harmstone wrote:
>> --- a/bfd/config.bfd
>> +++ b/bfd/config.bfd
>> @@ -249,9 +249,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"
>>      want64=true
>>      targ_underscore=no
>>      ;;
>
> Here and elsewhere - are you really targeting a 32-bit ABI (as per the
> title)? Or do you instead mean aarch64-*-mingw64, or yet more generically
> aarch64-*-mingw*? (From the *-s I used you can see that I also find a
> middle component "w64" odd.

Despite being 64 bit, the OS part of these triples have traditionally 
always been "mingw32" (where the arch part of the triple indicates whether 
it is 32 or 64 bit). Some tools/libraries/build systems only ever match 
for "mingw32" here, while some might tolerate "mingw64" too even though 
it's not the norm.

The "w64" bit in the vendor field is usually used to indicate the use of 
the "mingw-w64" fork of the mingw runtime (as opposed to the original 
mingw.org runtime). This is also used for 32 bit targets, such as 
i686-w64-mingw32.

// Martin
  
Mark Harmstone Dec. 20, 2022, 1:18 p.m. UTC | #3
On 18/12/22 22:44, Martin Storsjö wrote:
> On Fri, 16 Dec 2022, Jan Beulich via Binutils wrote:
>
>> On 16.12.2022 03:14, Mark Harmstone wrote:
>>> --- a/bfd/config.bfd
>>> +++ b/bfd/config.bfd
>>> @@ -249,9 +249,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"
>>>      want64=true
>>>      targ_underscore=no
>>>      ;;
>>
>> Here and elsewhere - are you really targeting a 32-bit ABI (as per the
>> title)? Or do you instead mean aarch64-*-mingw64, or yet more generically
>> aarch64-*-mingw*? (From the *-s I used you can see that I also find a
>> middle component "w64" odd.
>
> Despite being 64 bit, the OS part of these triples have traditionally always been "mingw32" (where the arch part of the triple indicates whether it is 32 or 64 bit). Some tools/libraries/build systems only ever match for "mingw32" here, while some might tolerate "mingw64" too even though it's not the norm.
>
> The "w64" bit in the vendor field is usually used to indicate the use of the "mingw-w64" fork of the mingw runtime (as opposed to the original mingw.org runtime). This is also used for 32 bit targets, such as i686-w64-mingw32.
>
> // Martin
>
Yes, as Martin says, it's a bit eclectic. aarch64-w64-mingw32 is also the name that LLVM is using already.

Mark
  

Patch

diff --git a/bfd/config.bfd b/bfd/config.bfd
index 92a6cff938b..a583ae9a424 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -249,9 +249,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"
     want64=true
     targ_underscore=no
     ;;
diff --git a/bfd/peicode.h b/bfd/peicode.h
index f7ba24ae10a..26e95dc1f1b 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -440,7 +440,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 5a3e5017b46..a88b66dae8f 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 6243a2b0c2d..b51aeb9f38f 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 a3c5e0f778e..c9c53919dbf 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 /* <address>      */
 };
 
+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 <option(s)> <object-file(s)>\n"), program_name);
   /* xgetext:c-format */
   fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
-  fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, thumb\n"));
+  fprintf (file, _("        possible <machine>: arm[_interwork], arm64, i386, mcore[-elf]{-le|-be}, thumb\n"));
   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
   fprintf (file, _("   -y --output-delaylib <outname> 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 83b08634c7f..1ae02598313 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 82f2d44f418..ba49003bc80 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 8df750f9dd0..231cdecb12b 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 741b246f67e..5f05f083bba 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -118,9 +118,9 @@  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_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 e2c538e6d99..0ecce1bc4c1 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -106,7 +106,7 @@  fragment <<EOF
 #define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
 #endif
 
-#ifdef TARGET_IS_i386pep
+#if defined(TARGET_IS_i386pep) || defined(TARGET_IS_aarch64pe)
 #define DLL_SUPPORT
 #endif
 
@@ -115,7 +115,7 @@  fragment <<EOF
 					 | IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA \
   					 | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)
 
-#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#if defined(TARGET_IS_i386pep) || defined(TARGET_IS_aarch64pe) || ! defined(DLL_SUPPORT)
 #define	PE_DEF_SUBSYSTEM		3
 #undef NT_EXE_IMAGE_BASE
 #define NT_EXE_IMAGE_BASE \
@@ -1541,14 +1541,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(TARGET_IS_aarch64pe)
   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(TARGET_IS_aarch64pe)
   else
     pep_exe_build_sections (link_info.output_bfd, &link_info);
 #endif
@@ -1844,6 +1844,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(TARGET_IS_aarch64pe)
+  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 df16e85bbe0..edfcda9cf16 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 <foo>
 
 0000000140001008 <foo>:
    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 83b20d0da45..58158cc657d 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 {