[PATCH v2 1/1] aarch64: mingw: Auto-import implementation
Evgeny Karpov <[email protected]> Fri, 31 Jul 2026 16:46:55 +0200
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
Auto-import is needed to resolve symbols during dynamic linking. For example, adrp x0, dyn_v + 2 add x0, x0, :lo12:dyn_v + 2 or adrp x0, dyn_v + 8 ldr x0, [x0, :lo12:dyn_v + 8] or b init_dyn_v bl init_dyn_v init_dyn_v and dyn_v are undefined at compile time and are getting resolved during linking with a dynamic library to the IAT (import address table). In case of b or bl, it can be done by using a jump table init_dyn_v: adrp x16, __imp_init_dyn_v add x16, x16, :lo12:__imp_init_dyn_v ldr x16, [x16] br x16 "adrp", "add" and "ldr" are handled differently. The codegen usually creates a reference to a symbol without an offset: adrp x0, <symbol> add x0, x0, :lo12:<symbol> / ldr x0, [x0, :lo12:<symbol>] however it might be necessary to support offsets in some cases: adrp x0, <symbol> +/- offset add x0, x0, :lo12:<symbol> +/- offset / ldr x0, [x0, :lo12:<symbol> +/- offset] It is handled by detecting relocations that have symbols that are resolved during dynamic linking. "adrp" is replaced by an unconditional branching to a place where a symbol address will be loaded from the IAT and then returning back. Relocation for the "add" and "ldr" instructions is not needed in this case. adrp x0, dyn_v + 8 add x0, x0, :lo12:dyn_v + 8 / ldr x0, [x0, :lo12:dyn_v + 8] turns into __fu1_dyn_v: b __imp_dyn_v_10_8 add x0, x0, 8 / ldr x0, [x0, 8] ... __imp_dyn_v_10_8: adrp x0, __imp_dyn_v ldr x0, [x0, :lo12:__imp_dyn_v] add x0, x0, offset_4k, lsl #12 b __fu1_dyn_v + 0x4 Another option that was considered is using bl / ret. However, in this case, an edge case will not be handled properly: adrp x30, dyn_v Signed-off-by: Evgeny Karpov <[email protected]> bfd/ChangeLog: * coff-aarch64.c (coff_pe_aarch64_relocate_section): Add relocation handling for dynamic linking. ld/ChangeLog: * emultempl/pep.em: Update read_addend for aarch64 relocations. * pe-dll.c (aarch64_make_jump_stub): Add jump stub. (aarch64_make_imp_offset): Add adrp handler for dynamic linking. (pe_create_import_fixup): Add fixups for aarch64. * testsuite/ld-pe/pe.exp: Add auto-import-aarch64 test. * testsuite/ld-pe/auto-import-aarch64.d: New test. * testsuite/ld-pe/auto-import-aarch64.s: New test. * testsuite/ld-pe/auto-import-dll-aarch64.s: New test. --- bfd/coff-aarch64.c | 56 +++--- ld/emultempl/pep.em | 17 +- ld/pe-dll.c | 171 +++++++++++++++++++ ld/testsuite/ld-pe/auto-import-aarch64.d | 167 ++++++++++++++++++ ld/testsuite/ld-pe/auto-import-aarch64.s | 61 +++++++ ld/testsuite/ld-pe/auto-import-dll-aarch64.s | 13 ++ ld/testsuite/ld-pe/pe.exp | 15 +- 7 files changed, 473 insertions(+), 27 deletions(-) create mode 100644 ld/testsuite/ld-pe/auto-import-aarch64.d create mode 100644 ld/testsuite/ld-pe/auto-import-aarch64.s create mode 100644 ld/testsuite/ld-pe/auto-import-dll-aarch64.s diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c index d889359a6fc..cd194034839 100644 --- a/bfd/coff-aarch64.c +++ b/bfd/coff-aarch64.c @@ -521,6 +521,38 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, h = obj_coff_sym_hashes (input_bfd)[symndx]; + if (h && h->root.type == bfd_link_hash_defweak) + switch (rel->r_type) + { + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + case IMAGE_REL_ARM64_PAGEOFFSET_12L: + { + rel->r_ignore = 1; + continue; + } + case IMAGE_REL_ARM64_BRANCH26: + { + h = (struct coff_link_hash_entry*) + bfd_link_hash_lookup (info->hash, h->root.root.string + 6, + 0, 0, 1); + break; + } + case IMAGE_REL_ARM64_PAGEBASE_REL21: + { + uint32_t opcode = 0x14000000; /* b <label>. */ + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_BRANCH26; + + char* imp_label = xasprintf("%s_%x_%lx", h->root.root.string, + input_section->id, + (long unsigned) rel->r_vaddr); + h = (struct coff_link_hash_entry*) + bfd_link_hash_lookup (info->hash, imp_label, 0, 0, 1); + free(imp_label); + break; + } + } + if (h && h->root.type == bfd_link_hash_defined) { sec = h->root.u.def.section; @@ -557,6 +589,7 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, continue; } + rel->r_ignore = 1; switch (rel->r_type) { case IMAGE_REL_ARM64_ADDR32NB: @@ -578,8 +611,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, input_section, rel->r_vaddr - input_section->vma); bfd_putl32 (val, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -613,8 +644,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= val & 0x3ffffff; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -648,8 +677,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= (val & 0x7ffff) << 5; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -683,8 +710,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= (val & 0x3fff) << 5; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -720,8 +745,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= (val & 0x1ffffc) << 3; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -757,8 +780,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= (val & 0x1ffffc) << 3; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -786,8 +807,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, input_section, rel->r_vaddr - input_section->vma); bfd_putl32 (val, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -831,8 +850,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= val << 10; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -854,8 +871,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, opcode |= val << 10; bfd_putl32 (opcode, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -875,8 +890,6 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, input_section, rel->r_vaddr - input_section->vma); bfd_putl32 (val, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } @@ -898,10 +911,7 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, s = s->next; } - bfd_putl16 (idx, contents + rel->r_vaddr); - rel->r_ignore = 1; - break; } diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 25ce3963b36..c74192ae32b 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1160,10 +1160,22 @@ pep_fixup_stdcalls (void) static bfd_vma read_addend (arelent *rel, asection *s) { - char buf[8]; bfd_vma addend = 0; bool ok = false; +#if defined (COFF_WITH_peAArch64) + switch (rel->howto->bitsize) + { + case 12: + case 21: + case 26: + ok = true; + break; + } + +#else + char buf[8]; + switch (rel->howto->bitsize) { case 8: @@ -1186,7 +1198,6 @@ read_addend (arelent *rel, asection *s) addend = bfd_get_16 (s->owner, buf); } break; - case 26: case 32: ok = bfd_get_section_contents (s->owner, s, buf, rel->address, 4); if (ok) @@ -1203,6 +1214,8 @@ read_addend (arelent *rel, asection *s) addend = bfd_get_64 (s->owner, buf); break; } +#endif + if (!ok) einfo (_("%P: %H: cannot get section contents - auto-import exception\n"), s->owner, s, rel->address); diff --git a/ld/pe-dll.c b/ld/pe-dll.c index f43bd14896e..b0a86f070d8 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -2842,10 +2842,181 @@ pe_create_runtime_relocator_reference (bfd *parent) return abfd; } +static void +aarch64_make_jump_stub(const char* symbol_name, bfd* parent) +{ + static struct bfd_hash_table *stub_hash = NULL; + if (!stub_hash) + { + stub_hash = (struct bfd_hash_table *) xmalloc + (sizeof (struct bfd_hash_table)); + bfd_hash_table_init (stub_hash, bfd_hash_newfunc, + sizeof (struct bfd_hash_entry)); + } + + if (pe_dll_extra_pe_debug) + printf ("validate jump stub for %s\n", symbol_name); + + if (bfd_hash_lookup(stub_hash, symbol_name, false, false)) + return; + + if (pe_dll_extra_pe_debug) + printf ("creating jump stub for %s\n", symbol_name); + bfd_hash_lookup(stub_hash, symbol_name, true, true); + + static unsigned tmp_stub_seq = 0; + char *oname = xasprintf ("jump_stub_d%06d.o", tmp_stub_seq); + ++tmp_stub_seq; + + bfd *abfd = bfd_create (oname, parent); + free (oname); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (12 * sizeof (asymbol *)); + + asection *tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS + | SEC_READONLY, 2); + quick_symbol (abfd, "", symbol_name, "", tx, BSF_GLOBAL, 0); + quick_symbol (abfd, "__imp_", symbol_name, "", bfd_und_section_ptr, + BSF_GLOBAL, 0); + + const unsigned jmp_byte_count = sizeof (jmp_aarch64_bytes); + bfd_set_section_size (tx, jmp_byte_count); + unsigned char *td = xmalloc (jmp_byte_count); + tx->contents = td; + memcpy (td, jmp_aarch64_bytes, jmp_byte_count); + + quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, 2); + quick_reloc (abfd, 4, BFD_RELOC_AARCH64_ADD_LO12, 2); + save_relocs (tx); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); + bfd_make_readable (abfd); + add_bfd_to_link (abfd, bfd_get_filename (abfd), &link_info); +} + +static void +aarch64_make_imp_offset(const char* imp_symbol_name, + const char* imp_offset_name, const int offset, + unsigned rd, const char* caller_label, bfd* parent) +{ + if (pe_dll_extra_pe_debug) + printf("symbol: %s imp_offset_name: %s offset: %u rs: %u caller: %s\n", + imp_symbol_name, imp_offset_name, offset, rd, caller_label); + + static const unsigned char imp_offset_bytes[] = + { + 0x00, 0x00, 0x00, 0x90, /* adrp x0, <imp_symbol_name> */ + 0x00, 0x00, 0x40, 0xf9, /* ldr x0, [x0, :lo12:<imp_symbol_name>] */ + 0x00, 0x00, 0x40, 0x91, /* add x0, x0, 0, lsl 12 */ + 0x01, 0x00, 0x00, 0x14 /* b <caller_label> + 4 */ + }; + + static unsigned tmp_stub_seq = 0; + char *oname = xasprintf ("imp_offset_stub_d%06d.o", tmp_stub_seq); + ++tmp_stub_seq; + + bfd *abfd = bfd_create (oname, parent); + free (oname); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (12 * sizeof (asymbol *)); + + asection *tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS + | SEC_READONLY, 2); + quick_symbol (abfd, "", imp_offset_name, "", tx, BSF_GLOBAL, 0); + quick_symbol (abfd, "", imp_symbol_name, "", UNDSEC, BSF_GLOBAL, 0); + quick_symbol (abfd, "", caller_label, "", UNDSEC, BSF_GLOBAL, 0); + + const unsigned imp_offset_byte_count = sizeof (imp_offset_bytes); + bfd_set_section_size (tx, imp_offset_byte_count); + uint32_t *td = xmalloc (imp_offset_byte_count); + tx->contents = (bfd_byte*) td; + memcpy (td, imp_offset_bytes, imp_offset_byte_count); + + rd &= (1 << 5) - 1; + td[0] |= rd; + td[1] |= (rd << 5) | rd; + + unsigned imm = 0; + if (offset >= 0) + imm = offset; + else + { + imm = -offset + 4096; +/* Change "add x0, x0, 0, lsl 12" to "sub x0, x0, 0, lsl 12". */ + td[2] |= 1 << 30; + } + imm >>= 12; + imm &= ((1 << 12) - 1); + td[2] |= (rd << 5) | rd; + td[2] |= imm << 10; + + quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_PCREL, 2); + quick_reloc (abfd, 4, BFD_RELOC_AARCH64_LDST64_LO12, 2); + quick_reloc (abfd, 12, BFD_RELOC_AARCH64_CALL26, 3); + save_relocs (tx); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, tx, td, 0, imp_offset_byte_count); + bfd_make_readable (abfd); + add_bfd_to_link (abfd, bfd_get_filename (abfd), &link_info); +} + void pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend, char *name, const char *symname) { + if (pe_details->pe_arch == PE_ARCH_aarch64) + { + if (rel->howto->bitsize == 12) + return; + else if (rel->howto->bitsize == 26) + { +/* On AArch64, a single opcode is not sufficient for relocation + in dynamic linking. The linker generates a jump stub instead. */ + aarch64_make_jump_stub(name, s->owner); + return; + } + else if (rel->howto->bitsize == 21) + { + uint32_t opcode; + if (!bfd_get_section_contents (s->owner, s, &opcode, + rel->address, 4)) + return; + + int32_t imm = (opcode >> 5) & ((1 << 19) - 1); + imm <<= 2; + imm |= (opcode >> 29) & ((1 << 2) - 1); + if (imm & (1 << 20)) + imm |= ~((1 << 21) - 1); + + char *imp_offset_label = xasprintf("__imp_%s", name); + char *imp_label = xasprintf("%s_%x_%lx", imp_offset_label, + current_sec->id, + (long unsigned) rel->address); + const char *fixup_name = make_import_fixup_mark (rel, name); + unsigned rd = opcode & ((1 << 5) - 1); + aarch64_make_imp_offset(imp_offset_label, imp_label, imm, rd, + fixup_name, s->owner); + + free(imp_label); + free(imp_offset_label); + return; + } + } + const char *fixup_name = make_import_fixup_mark (rel, name); bfd *b; diff --git a/ld/testsuite/ld-pe/auto-import-aarch64.d b/ld/testsuite/ld-pe/auto-import-aarch64.d new file mode 100644 index 00000000000..4b70cfedd2a --- /dev/null +++ b/ld/testsuite/ld-pe/auto-import-aarch64.d @@ -0,0 +1,167 @@ + +.*: file format pei-aarch64-little + + +Disassembly of section .text: + +0000000140001000 <.*>: + 140001000: 14000030 b 1400010c0 <__imp_dyn_v_10_0> + 140001004: 91000000 add x0, x0, #0x0 + 140001008: f9400000 ldr x0, \[x0\] + +000000014000100c <__fu1_dyn_v>: + 14000100c: 14000031 b 1400010d0 <__imp_dyn_v_10_c> + 140001010: 91000800 add x0, x0, #0x2 + 140001014: f9400400 ldr x0, \[x0, #8\] + +0000000140001018 <__fu2_dyn_v>: + 140001018: 14000032 b 1400010e0 <__imp_dyn_v_10_18> + 14000101c: 913ffc00 add x0, x0, #0xfff + 140001020: f947fc00 ldr x0, \[x0, #4088\] + +0000000140001024 <__fu3_dyn_v>: + 140001024: 14000033 b 1400010f0 <__imp_dyn_v_10_24> + 140001028: 91000000 add x0, x0, #0x0 + 14000102c: f9400000 ldr x0, \[x0\] + +0000000140001030 <__fu4_dyn_v>: + 140001030: 14000034 b 140001100 <__imp_dyn_v_10_30> + 140001034: 912eb000 add x0, x0, #0xbac + 140001038: f945d800 ldr x0, \[x0, #2992\] + +000000014000103c <__fu5_dyn_v>: + 14000103c: 14000035 b 140001110 <__imp_dyn_v_10_3c> + 140001040: 913ffc00 add x0, x0, #0xfff + 140001044: f947fc00 ldr x0, \[x0, #4088\] + +0000000140001048 <__fu6_dyn_v>: + 140001048: 14000036 b 140001120 <__imp_dyn_v_10_48> + 14000104c: 913ff800 add x0, x0, #0xffe + 140001050: f947fc00 ldr x0, \[x0, #4088\] + +0000000140001054 <__fu7_dyn_v>: + 140001054: 14000037 b 140001130 <__imp_dyn_v_10_54> + 140001058: 91000400 add x0, x0, #0x1 + 14000105c: f9400400 ldr x0, \[x0, #8\] + +0000000140001060 <__fu8_dyn_v>: + 140001060: 14000038 b 140001140 <__imp_dyn_v_10_60> + 140001064: 91000000 add x0, x0, #0x0 + 140001068: f9400000 ldr x0, \[x0\] + +000000014000106c <__fu9_dyn_v>: + 14000106c: 14000039 b 140001150 <__imp_dyn_v_10_6c> + 140001070: 91115000 add x0, x0, #0x454 + 140001074: f9422800 ldr x0, \[x0, #1104\] + +0000000140001078 <__fu10_dyn_v>: + 140001078: 1400003a b 140001160 <__imp_dyn_v_10_78> + 14000107c: 91000000 add x0, x0, #0x0 + 140001080: f9400000 ldr x0, \[x0\] + +0000000140001084 <__fu11_dyn_v>: + 140001084: 1400003b b 140001170 <__imp_dyn_v_10_84> + 140001088: 91000821 add x1, x1, #0x2 + 14000108c: f9400421 ldr x1, \[x1, #8\] + +0000000140001090 <__fu12_dyn_v>: + 140001090: 1400003c b 140001180 <__imp_dyn_v_10_90> + 140001094: 91000820 add x0, x1, #0x2 + 140001098: f9400420 ldr x0, \[x1, #8\] + +000000014000109c <__fu13_dyn_v>: + 14000109c: 1400003d b 140001190 <__imp_dyn_v_10_9c> + 1400010a0: 913ff821 add x1, x1, #0xffe + 1400010a4: f947fc21 ldr x1, \[x1, #4088\] + 1400010a8: 14000002 b 1400010b0 <init_dyn_v> + 1400010ac: 94000001 bl 1400010b0 <init_dyn_v> + +00000001400010b0 <init_dyn_v>: + 1400010b0: d0000010 adrp x16, 140003000 <.*> + 1400010b4: 91012210 add x16, x16, #0x48 + 1400010b8: f9400210 ldr x16, \[x16\] + 1400010bc: d61f0200 br x16 + +00000001400010c0 <__imp_dyn_v_10_0>: + 1400010c0: d0000000 adrp x0, 140003000 <.*> + 1400010c4: f9402000 ldr x0, \[x0, #64\] + 1400010c8: 91400000 add x0, x0, #0x0, lsl #12 + 1400010cc: 17ffffce b 140001004 <.*\+0x4> + +00000001400010d0 <__imp_dyn_v_10_c>: + 1400010d0: d0000000 adrp x0, 140003000 <.*> + 1400010d4: f9402000 ldr x0, \[x0, #64\] + 1400010d8: 91400000 add x0, x0, #0x0, lsl #12 + 1400010dc: 17ffffcd b 140001010 <__fu1_dyn_v\+0x4> + +00000001400010e0 <__imp_dyn_v_10_18>: + 1400010e0: d0000000 adrp x0, 140003000 <.*> + 1400010e4: f9402000 ldr x0, \[x0, #64\] + 1400010e8: 91400000 add x0, x0, #0x0, lsl #12 + 1400010ec: 17ffffcc b 14000101c <__fu2_dyn_v\+0x4> + +00000001400010f0 <__imp_dyn_v_10_24>: + 1400010f0: d0000000 adrp x0, 140003000 <.*> + 1400010f4: f9402000 ldr x0, \[x0, #64\] + 1400010f8: 91400400 add x0, x0, #0x1, lsl #12 + 1400010fc: 17ffffcb b 140001028 <__fu3_dyn_v\+0x4> + +0000000140001100 <__imp_dyn_v_10_30>: + 140001100: d0000000 adrp x0, 140003000 <.*> + 140001104: f9402000 ldr x0, \[x0, #64\] + 140001108: 91436c00 add x0, x0, #0xdb, lsl #12 + 14000110c: 17ffffca b 140001034 <__fu4_dyn_v\+0x4> + +0000000140001110 <__imp_dyn_v_10_3c>: + 140001110: d0000000 adrp x0, 140003000 <.*> + 140001114: f9402000 ldr x0, \[x0, #64\] + 140001118: 9143fc00 add x0, x0, #0xff, lsl #12 + 14000111c: 17ffffc9 b 140001040 <__fu5_dyn_v\+0x4> + +0000000140001120 <__imp_dyn_v_10_48>: + 140001120: d0000000 adrp x0, 140003000 <.*> + 140001124: f9402000 ldr x0, \[x0, #64\] + 140001128: d1400400 sub x0, x0, #0x1, lsl #12 + 14000112c: 17ffffc8 b 14000104c <__fu6_dyn_v\+0x4> + +0000000140001130 <__imp_dyn_v_10_54>: + 140001130: d0000000 adrp x0, 140003000 <.*> + 140001134: f9402000 ldr x0, \[x0, #64\] + 140001138: d1400400 sub x0, x0, #0x1, lsl #12 + 14000113c: 17ffffc7 b 140001058 <__fu7_dyn_v\+0x4> + +0000000140001140 <__imp_dyn_v_10_60>: + 140001140: d0000000 adrp x0, 140003000 <.*> + 140001144: f9402000 ldr x0, \[x0, #64\] + 140001148: d1400800 sub x0, x0, #0x2, lsl #12 + 14000114c: 17ffffc6 b 140001064 <__fu8_dyn_v\+0x4> + +0000000140001150 <__imp_dyn_v_10_6c>: + 140001150: d0000000 adrp x0, 140003000 <.*> + 140001154: f9402000 ldr x0, \[x0, #64\] + 140001158: d1437000 sub x0, x0, #0xdc, lsl #12 + 14000115c: 17ffffc5 b 140001070 <__fu9_dyn_v\+0x4> + +0000000140001160 <__imp_dyn_v_10_78>: + 140001160: d0000000 adrp x0, 140003000 <.*> + 140001164: f9402000 ldr x0, \[x0, #64\] + 140001168: d1440400 sub x0, x0, #0x101, lsl #12 + 14000116c: 17ffffc4 b 14000107c <__fu10_dyn_v\+0x4> + +0000000140001170 <__imp_dyn_v_10_84>: + 140001170: d0000001 adrp x1, 140003000 <.*> + 140001174: f9402021 ldr x1, \[x1, #64\] + 140001178: 91400021 add x1, x1, #0x0, lsl #12 + 14000117c: 17ffffc3 b 140001088 <__fu11_dyn_v\+0x4> + +0000000140001180 <__imp_dyn_v_10_90>: + 140001180: d0000001 adrp x1, 140003000 <.*> + 140001184: f9402021 ldr x1, \[x1, #64\] + 140001188: 91400021 add x1, x1, #0x0, lsl #12 + 14000118c: 17ffffc2 b 140001094 <__fu12_dyn_v\+0x4> + +0000000140001190 <__imp_dyn_v_10_9c>: + 140001190: d0000001 adrp x1, 140003000 <.*> + 140001194: f9402021 ldr x1, \[x1, #64\] + 140001198: d1400421 sub x1, x1, #0x1, lsl #12 + 14000119c: 17ffffc1 b 1400010a0 <__fu13_dyn_v\+0x4> diff --git a/ld/testsuite/ld-pe/auto-import-aarch64.s b/ld/testsuite/ld-pe/auto-import-aarch64.s new file mode 100644 index 00000000000..411669e9d9e --- /dev/null +++ b/ld/testsuite/ld-pe/auto-import-aarch64.s @@ -0,0 +1,61 @@ + .text + .global main +main: + adrp x0, dyn_v + add x0, x0, :lo12:dyn_v + ldr x0, [x0, :lo12:dyn_v] + + adrp x0, dyn_v + 2 + add x0, x0, :lo12:dyn_v + 2 + ldr x0, [x0, :lo12:dyn_v + 8] + + adrp x0, dyn_v + 4095 + add x0, x0, :lo12:dyn_v + 4095 + ldr x0, [x0, :lo12:dyn_v + 4088] + + adrp x0, dyn_v + 4096 + add x0, x0, :lo12:dyn_v + 4096 + ldr x0, [x0, :lo12:dyn_v + 4096] + + adrp x0, dyn_v + 900012 + add x0, x0, :lo12:dyn_v + 900012 + ldr x0, [x0, :lo12:dyn_v + 900016] + + adrp x0, dyn_v + 1048575 + add x0, x0, :lo12:dyn_v + 1048575 + ldr x0, [x0, :lo12:dyn_v + 1048568] + + adrp x0, dyn_v - 2 + add x0, x0, :lo12:dyn_v - 2 + ldr x0, [x0, :lo12:dyn_v - 8] + + adrp x0, dyn_v - 4095 + add x0, x0, :lo12:dyn_v - 4095 + ldr x0, [x0, :lo12:dyn_v - 4088] + + adrp x0, dyn_v - 4096 + add x0, x0, :lo12:dyn_v - 4096 + ldr x0, [x0, :lo12:dyn_v - 4096] + + adrp x0, dyn_v - 900012 + add x0, x0, :lo12:dyn_v - 900012 + ldr x0, [x0, :lo12:dyn_v - 900016] + + adrp x0, dyn_v - 1048576 + add x0, x0, :lo12:dyn_v - 1048576 + ldr x0, [x0, :lo12:dyn_v - 1048576] + + adrp x1, dyn_v + 2 + add x1, x1, :lo12:dyn_v + 2 + ldr x1, [x1, :lo12:dyn_v + 8] + + adrp x1, dyn_v + 2 + add x0, x1, :lo12:dyn_v + 2 + ldr x0, [x1, :lo12:dyn_v + 8] + + adrp x1, dyn_v - 2 + add x1, x1, :lo12:dyn_v - 2 + ldr x1, [x1, :lo12:dyn_v - 8] + + b init_dyn_v + bl init_dyn_v diff --git a/ld/testsuite/ld-pe/auto-import-dll-aarch64.s b/ld/testsuite/ld-pe/auto-import-dll-aarch64.s new file mode 100644 index 00000000000..dc9314273fa --- /dev/null +++ b/ld/testsuite/ld-pe/auto-import-dll-aarch64.s @@ -0,0 +1,13 @@ + .data + .global dyn_v + .align 3 + .def dyn_v; .scl 2; .type 0; .endef +dyn_v: + .space 8 + + .text + .align 2 + .global init_dyn_v + .def init_dyn_v; .scl 2; .type 32; .endef +init_dyn_v: + ret diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp index b95f61b8578..53b04bb6757 100644 --- a/ld/testsuite/ld-pe/pe.exp +++ b/ld/testsuite/ld-pe/pe.exp @@ -121,6 +121,17 @@ if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} { } run_ld_link_tests $pe_tests + + set auto_import_aarch64_test "auto-import-aarch64" + if { [ld_assemble $as $srcdir/$subdir/auto-import-dll-aarch64.s tmpdir/auto-import-dll-aarch64.o] + && [ld_assemble $as $srcdir/$subdir/auto-import-aarch64.s tmpdir/auto-import-aarch64.o] + && [ld_link $ld "tmpdir/auto-import-dll.dll" "-shared tmpdir/auto-import-dll-aarch64.o --out-implib tmpdir/libauto-import-dll-aarch64.a"] + && [ld_link $ld "tmpdir/auto-import-aarch64.exe" "tmpdir/auto-import-aarch64.o tmpdir/libauto-import-dll-aarch64.a"] + && [regexp [file_contents "$srcdir/$subdir/auto-import-aarch64.d"] [run_host_cmd "$objdump" "-d tmpdir/auto-import-aarch64.exe"]] } { + pass $auto_import_aarch64_test + } else { + fail $auto_import_aarch64_test + } } run_dump_test "image_size" @@ -185,10 +196,10 @@ if [check_shared_lib_support] { } run_dump_test "symbols-ordinals-hints-exports-ld" # no dlltool for these two - setup_xfail aarch64-*-* sh-*-* + setup_xfail sh-*-* run_dump_test "symbols-ordinals-hints-exports-dlltool" run_dump_test "symbols-ordinals-hints-imports-ld" - setup_xfail aarch64-*-* sh-*-* + setup_xfail sh-*-* run_dump_test "symbols-ordinals-hints-imports-dlltool" set ASFLAGS $old_ASFLAGS }