Skip to content

Commit 8fe4480

Browse files
committed
adrp
1 parent 488c089 commit 8fe4480

2 files changed

Lines changed: 23 additions & 9 deletions

File tree

winsup/cygwin/mm/malloc_wrapper.cc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,29 @@ import_address (void *imp)
5151
__try
5252
{
5353
#if defined(__aarch64__)
54-
// If opcode is an adr instruction.
55-
uint32_t opcode = *(uint32_t *) imp;
56-
if ((opcode & 0x9f000000) == 0x10000000)
54+
// If opcode1 is an adr instruction (https://www.scs.stanford.edu/~zyedidia/arm64/adr.html)
55+
uint32_t opcode1 = *((uint32_t *) imp);
56+
uint32_t opcode2 = *(((uint32_t *) imp) + 1);
57+
if ((opcode1 & 0x9f000000) == 0x10000000)
5758
{
58-
uint32_t immhi = (opcode >> 5) & 0x7ffff;
59-
uint32_t immlo = (opcode >> 29) & 0x3;
60-
int64_t sign_extend = (0l - (immhi >> 18)) << 21;
59+
uint32_t immhi = (opcode1 >> 5) & 0x7ffff;
60+
uint32_t immlo = (opcode1 >> 29) & 0x3;
61+
int64_t sign_extend = (0l - (immhi >> 20)) << 21; // sign extend from 21 to 64 bits
6162
int64_t imm = sign_extend | (immhi << 2) | immlo;
62-
uintptr_t jmpto = *(uintptr_t *) ((uint8_t *) imp + imm);
63+
uintptr_t jmpto = *(uintptr_t *) ((int64_t) imp + imm);
64+
return (void *) jmpto;
65+
}
66+
// If opcode1 is an adrp and opcode2 is ldr instruction (https://www.scs.stanford.edu/~zyedidia/arm64/adrp.html,
67+
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_gen.html).
68+
else if (((opcode1 & 0x9f000000) == 0x90000000) && ((opcode2 & 0xbfc00000) == 0xb9400000))
69+
{
70+
uint32_t immhi = (opcode1 >> 5) & 0x7ffff;
71+
uint32_t immlo = (opcode1 >> 29) & 0x3;
72+
uint32_t imm12 = ((opcode2 >> 10) & 0xfff) * 8; // 64 bit scale
73+
int64_t sign_extend = (0l - ((int64_t) immhi >> 32)) << 33; // sign extend from 33 to 64 bits
74+
int64_t imm = sign_extend | (((immhi << 2) | immlo) << 12);
75+
int64_t base = (int64_t) imp & ~0xfff;
76+
uintptr_t jmpto = *(uintptr_t *) (base + imm + imm12);
6377
return (void *) jmpto;
6478
}
6579
#else

winsup/cygwin/scripts/mkimport

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ EOF
7373
.extern $imp_sym
7474
.global $glob_sym
7575
$glob_sym:
76-
adr x16, $imp_sym
77-
ldr x16, [x16]
76+
adrp x16, $imp_sym
77+
ldr x16, [x16, #:lo12:$imp_sym]
7878
br x16
7979
EOF
8080
} else {

0 commit comments

Comments
 (0)