mirror of
https://github.com/python/cpython.git
synced 2026-04-15 08:11:10 +00:00
GH-146128: Remove the buggy AArch64 "33rx" relocation (#146263)
This commit is contained in:
parent
132abfd135
commit
6bb7b33e8f
4 changed files with 10 additions and 116 deletions
73
Python/jit.c
73
Python/jit.c
|
|
@ -355,18 +355,6 @@ patch_aarch64_12(unsigned char *location, uint64_t value)
|
|||
set_bits(loc32, 10, value, shift, 12);
|
||||
}
|
||||
|
||||
// Relaxable 12-bit low part of an absolute address. Pairs nicely with
|
||||
// patch_aarch64_21rx (below).
|
||||
void
|
||||
patch_aarch64_12x(unsigned char *location, uint64_t value)
|
||||
{
|
||||
// This can *only* be relaxed if it occurs immediately before a matching
|
||||
// patch_aarch64_21rx. If that happens, the JIT build step will replace both
|
||||
// calls with a single call to patch_aarch64_33rx. Otherwise, we end up
|
||||
// here, and the instruction is patched normally:
|
||||
patch_aarch64_12(location, value);
|
||||
}
|
||||
|
||||
// 16-bit low part of an absolute address.
|
||||
void
|
||||
patch_aarch64_16a(unsigned char *location, uint64_t value)
|
||||
|
|
@ -427,18 +415,6 @@ patch_aarch64_21r(unsigned char *location, uint64_t value)
|
|||
set_bits(loc32, 5, value, 2, 19);
|
||||
}
|
||||
|
||||
// Relaxable 21-bit count of pages between this page and an absolute address's
|
||||
// page. Pairs nicely with patch_aarch64_12x (above).
|
||||
void
|
||||
patch_aarch64_21rx(unsigned char *location, uint64_t value)
|
||||
{
|
||||
// This can *only* be relaxed if it occurs immediately before a matching
|
||||
// patch_aarch64_12x. If that happens, the JIT build step will replace both
|
||||
// calls with a single call to patch_aarch64_33rx. Otherwise, we end up
|
||||
// here, and the instruction is patched normally:
|
||||
patch_aarch64_21r(location, value);
|
||||
}
|
||||
|
||||
// 21-bit relative branch.
|
||||
void
|
||||
patch_aarch64_19r(unsigned char *location, uint64_t value)
|
||||
|
|
@ -469,55 +445,6 @@ patch_aarch64_26r(unsigned char *location, uint64_t value)
|
|||
set_bits(loc32, 0, value, 2, 26);
|
||||
}
|
||||
|
||||
// A pair of patch_aarch64_21rx and patch_aarch64_12x.
|
||||
void
|
||||
patch_aarch64_33rx(unsigned char *location, uint64_t value)
|
||||
{
|
||||
uint32_t *loc32 = (uint32_t *)location;
|
||||
// Try to relax the pair of GOT loads into an immediate value:
|
||||
assert(IS_AARCH64_ADRP(*loc32));
|
||||
unsigned char reg = get_bits(loc32[0], 0, 5);
|
||||
assert(IS_AARCH64_LDR_OR_STR(loc32[1]));
|
||||
// There should be only one register involved:
|
||||
assert(reg == get_bits(loc32[1], 0, 5)); // ldr's output register.
|
||||
assert(reg == get_bits(loc32[1], 5, 5)); // ldr's input register.
|
||||
uint64_t relaxed = *(uint64_t *)value;
|
||||
if (relaxed < (1UL << 16)) {
|
||||
// adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; nop
|
||||
loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg;
|
||||
loc32[1] = 0xD503201F;
|
||||
return;
|
||||
}
|
||||
if (relaxed < (1ULL << 32)) {
|
||||
// adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; movk reg, YYY
|
||||
loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg;
|
||||
loc32[1] = 0xF2A00000 | (get_bits(relaxed, 16, 16) << 5) | reg;
|
||||
return;
|
||||
}
|
||||
int64_t page_delta = (relaxed >> 12) - ((uintptr_t)location >> 12);
|
||||
if (page_delta >= -(1L << 20) &&
|
||||
page_delta < (1L << 20))
|
||||
{
|
||||
// adrp reg, AAA; ldr reg, [reg + BBB] -> adrp reg, AAA; add reg, reg, BBB
|
||||
patch_aarch64_21rx(location, relaxed);
|
||||
loc32[1] = 0x91000000 | get_bits(relaxed, 0, 12) << 10 | reg << 5 | reg;
|
||||
return;
|
||||
}
|
||||
relaxed = value - (uintptr_t)location;
|
||||
if ((relaxed & 0x3) == 0 &&
|
||||
(int64_t)relaxed >= -(1L << 19) &&
|
||||
(int64_t)relaxed < (1L << 19))
|
||||
{
|
||||
// adrp reg, AAA; ldr reg, [reg + BBB] -> ldr reg, XXX; nop
|
||||
loc32[0] = 0x58000000 | (get_bits(relaxed, 2, 19) << 5) | reg;
|
||||
loc32[1] = 0xD503201F;
|
||||
return;
|
||||
}
|
||||
// Couldn't do it. Just patch the two instructions normally:
|
||||
patch_aarch64_21rx(location, value);
|
||||
patch_aarch64_12x(location + 4, value);
|
||||
}
|
||||
|
||||
// Relaxable 32-bit relative address.
|
||||
void
|
||||
patch_x86_64_32rx(unsigned char *location, uint64_t value)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue