0
0
mirror of https://github.com/python/cpython.git synced 2024-12-01 11:15:56 +01:00

GH-115802: Don't JIT zero-length jumps (GH-116177)

This commit is contained in:
Brandt Bucher 2024-03-04 10:13:10 -08:00 committed by GitHub
parent 8a84eb75a9
commit 981f27dcc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -63,7 +63,7 @@ class Hole:
f"HoleKind_{self.kind}",
f"HoleValue_{self.value.name}",
f"&{self.symbol}" if self.symbol else "NULL",
_format_addend(self.addend),
f"{_signed(self.addend):#x}",
]
return f"{{{', '.join(parts)}}}"
@ -124,6 +124,56 @@ class Stencil:
):
self.holes.append(hole.replace(offset=base + 4 * i, kind=kind))
def remove_jump(self) -> None:
"""Remove a zero-length continuation jump, if it exists."""
hole = max(self.holes, key=lambda hole: hole.offset)
match hole:
case Hole(
offset=offset,
kind="IMAGE_REL_AMD64_REL32",
value=HoleValue.GOT,
symbol="_JIT_CONTINUE",
addend=-4,
) as hole:
# jmp qword ptr [rip]
jump = b"\x48\xFF\x25\x00\x00\x00\x00"
offset -= 3
case Hole(
offset=offset,
kind="IMAGE_REL_I386_REL32" | "X86_64_RELOC_BRANCH",
value=HoleValue.CONTINUE,
symbol=None,
addend=-4,
) as hole:
# jmp 5
jump = b"\xE9\x00\x00\x00\x00"
offset -= 1
case Hole(
offset=offset,
kind="R_AARCH64_JUMP26",
value=HoleValue.CONTINUE,
symbol=None,
addend=0,
) as hole:
# b #4
jump = b"\x00\x00\x00\x14"
case Hole(
offset=offset,
kind="R_X86_64_GOTPCRELX",
value=HoleValue.GOT,
symbol="_JIT_CONTINUE",
addend=addend,
) as hole:
assert _signed(addend) == -4
# jmp qword ptr [rip]
jump = b"\xFF\x25\x00\x00\x00\x00"
offset -= 2
case _:
return
if self.body[offset:] == jump:
self.body = self.body[:offset]
self.holes.remove(hole)
@dataclasses.dataclass
class StencilGroup:
@ -142,10 +192,19 @@ class StencilGroup:
def process_relocations(self, *, alignment: int = 1) -> None:
"""Fix up all GOT and internal relocations for this stencil group."""
for hole in self.code.holes.copy():
if (
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26"}
and hole.value is HoleValue.ZERO
):
self.code.pad(alignment)
self.code.emit_aarch64_trampoline(hole)
self.code.pad(alignment)
self.code.holes.remove(hole)
self.code.remove_jump()
self.code.pad(alignment)
self.data.pad(8)
for stencil in [self.code, self.data]:
holes = []
for hole in stencil.holes:
if hole.value is HoleValue.GOT:
assert hole.symbol is not None
@ -156,12 +215,6 @@ class StencilGroup:
hole.value, addend = self.symbols[hole.symbol]
hole.addend += addend
hole.symbol = None
elif (
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26"}
and hole.value is HoleValue.ZERO
):
self.code.emit_aarch64_trampoline(hole)
continue
elif (
hole.kind in {"IMAGE_REL_AMD64_REL32"}
and hole.value is HoleValue.ZERO
@ -169,9 +222,6 @@ class StencilGroup:
raise ValueError(
f"Add PyAPI_FUNC(...) or PyAPI_DATA(...) to declaration of {hole.symbol}!"
)
holes.append(hole)
stencil.holes[:] = holes
self.code.pad(alignment)
self._emit_global_offset_table()
self.code.holes.sort(key=lambda hole: hole.offset)
self.data.holes.sort(key=lambda hole: hole.offset)
@ -195,8 +245,9 @@ class StencilGroup:
if value_part and not symbol and not addend:
addend_part = ""
else:
signed = "+" if symbol is not None else ""
addend_part = f"&{symbol}" if symbol else ""
addend_part += _format_addend(addend, signed=symbol is not None)
addend_part += f"{_signed(addend):{signed}#x}"
if value_part:
value_part += "+"
self.data.disassembly.append(
@ -220,8 +271,8 @@ def symbol_to_value(symbol: str) -> tuple[HoleValue, str | None]:
return HoleValue.ZERO, symbol
def _format_addend(addend: int, signed: bool = False) -> str:
addend %= 1 << 64
if addend & (1 << 63):
addend -= 1 << 64
return f"{addend:{'+#x' if signed else '#x'}}"
def _signed(value: int) -> int:
value %= 1 << 64
if value & (1 << 63):
value -= 1 << 64
return value