diff options
Diffstat (limited to 'winsup/cygwin/mm/malloc_wrapper.cc')
-rw-r--r-- | winsup/cygwin/mm/malloc_wrapper.cc | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/winsup/cygwin/mm/malloc_wrapper.cc b/winsup/cygwin/mm/malloc_wrapper.cc index de3cf7d..9444cb4 100644 --- a/winsup/cygwin/mm/malloc_wrapper.cc +++ b/winsup/cygwin/mm/malloc_wrapper.cc @@ -50,6 +50,35 @@ import_address (void *imp) { __try { +#if defined(__aarch64__) + /* If first three instructions of the imp are: + adrp x16, X + ldr x16, [x16, #:lo12:X] + br x16 + References: + - https://www.scs.stanford.edu/~zyedidia/arm64/adrp.html + - https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_gen.html + - https://www.scs.stanford.edu/~zyedidia/arm64/br.html + NOTE: This implementation assumes that the relocation table is made of + those specific AArch64 instructions as generated by the + winsup/cygwin/scripts/mkimport script. Please, keep it in sync. */ + uint32_t opcode1 = *((uint32_t *) imp); + uint32_t opcode2 = *(((uint32_t *) imp) + 1); + uint32_t opcode3 = *(((uint32_t *) imp) + 2); + if (((opcode1 & 0x9f00001f) == 0x90000010) && + ((opcode2 & 0xffc003ff) == 0xf9400210) && + (opcode3 == 0xd61f0200)) + { + uint32_t immhi = (opcode1 >> 5) & 0x7ffff; + uint32_t immlo = (opcode1 >> 29) & 0x3; + uint32_t imm12 = ((opcode2 >> 10) & 0xfff) * 8; // 64 bit scale + int64_t sign_extend = (0l - ((int64_t) immhi >> 32)) << 33; // sign extend from 33 to 64 bits + int64_t imm = sign_extend | (((immhi << 2) | immlo) << 12); + int64_t base = (int64_t) imp & ~0xfff; + uintptr_t* jmpto = (uintptr_t *) (base + imm + imm12); + return (void *) *jmpto; + } +#else if (*((uint16_t *) imp) == 0x25ff) { const char *ptr = (const char *) imp; @@ -57,6 +86,7 @@ import_address (void *imp) (ptr + 6 + *(int32_t *)(ptr + 2)); return (void *) *jmpto; } +#endif } __except (NO_ERROR) {} __endtry |