Skip to content

Commit 981f27d

Browse files
authored
GH-115802: Don't JIT zero-length jumps (GH-116177)
1 parent 8a84eb7 commit 981f27d

File tree

1 file changed

+68
-17
lines changed

1 file changed

+68
-17
lines changed

Tools/jit/_stencils.py

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def as_c(self) -> str:
6363
f"HoleKind_{self.kind}",
6464
f"HoleValue_{self.value.name}",
6565
f"&{self.symbol}" if self.symbol else "NULL",
66-
_format_addend(self.addend),
66+
f"{_signed(self.addend):#x}",
6767
]
6868
return f"{{{', '.join(parts)}}}"
6969

@@ -124,6 +124,56 @@ def emit_aarch64_trampoline(self, hole: Hole) -> None:
124124
):
125125
self.holes.append(hole.replace(offset=base + 4 * i, kind=kind))
126126

127+
def remove_jump(self) -> None:
128+
"""Remove a zero-length continuation jump, if it exists."""
129+
hole = max(self.holes, key=lambda hole: hole.offset)
130+
match hole:
131+
case Hole(
132+
offset=offset,
133+
kind="IMAGE_REL_AMD64_REL32",
134+
value=HoleValue.GOT,
135+
symbol="_JIT_CONTINUE",
136+
addend=-4,
137+
) as hole:
138+
# jmp qword ptr [rip]
139+
jump = b"\x48\xFF\x25\x00\x00\x00\x00"
140+
offset -= 3
141+
case Hole(
142+
offset=offset,
143+
kind="IMAGE_REL_I386_REL32" | "X86_64_RELOC_BRANCH",
144+
value=HoleValue.CONTINUE,
145+
symbol=None,
146+
addend=-4,
147+
) as hole:
148+
# jmp 5
149+
jump = b"\xE9\x00\x00\x00\x00"
150+
offset -= 1
151+
case Hole(
152+
offset=offset,
153+
kind="R_AARCH64_JUMP26",
154+
value=HoleValue.CONTINUE,
155+
symbol=None,
156+
addend=0,
157+
) as hole:
158+
# b #4
159+
jump = b"\x00\x00\x00\x14"
160+
case Hole(
161+
offset=offset,
162+
kind="R_X86_64_GOTPCRELX",
163+
value=HoleValue.GOT,
164+
symbol="_JIT_CONTINUE",
165+
addend=addend,
166+
) as hole:
167+
assert _signed(addend) == -4
168+
# jmp qword ptr [rip]
169+
jump = b"\xFF\x25\x00\x00\x00\x00"
170+
offset -= 2
171+
case _:
172+
return
173+
if self.body[offset:] == jump:
174+
self.body = self.body[:offset]
175+
self.holes.remove(hole)
176+
127177

128178
@dataclasses.dataclass
129179
class StencilGroup:
@@ -142,10 +192,19 @@ class StencilGroup:
142192

143193
def process_relocations(self, *, alignment: int = 1) -> None:
144194
"""Fix up all GOT and internal relocations for this stencil group."""
195+
for hole in self.code.holes.copy():
196+
if (
197+
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26"}
198+
and hole.value is HoleValue.ZERO
199+
):
200+
self.code.pad(alignment)
201+
self.code.emit_aarch64_trampoline(hole)
202+
self.code.pad(alignment)
203+
self.code.holes.remove(hole)
204+
self.code.remove_jump()
145205
self.code.pad(alignment)
146206
self.data.pad(8)
147207
for stencil in [self.code, self.data]:
148-
holes = []
149208
for hole in stencil.holes:
150209
if hole.value is HoleValue.GOT:
151210
assert hole.symbol is not None
@@ -156,22 +215,13 @@ def process_relocations(self, *, alignment: int = 1) -> None:
156215
hole.value, addend = self.symbols[hole.symbol]
157216
hole.addend += addend
158217
hole.symbol = None
159-
elif (
160-
hole.kind in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26"}
161-
and hole.value is HoleValue.ZERO
162-
):
163-
self.code.emit_aarch64_trampoline(hole)
164-
continue
165218
elif (
166219
hole.kind in {"IMAGE_REL_AMD64_REL32"}
167220
and hole.value is HoleValue.ZERO
168221
):
169222
raise ValueError(
170223
f"Add PyAPI_FUNC(...) or PyAPI_DATA(...) to declaration of {hole.symbol}!"
171224
)
172-
holes.append(hole)
173-
stencil.holes[:] = holes
174-
self.code.pad(alignment)
175225
self._emit_global_offset_table()
176226
self.code.holes.sort(key=lambda hole: hole.offset)
177227
self.data.holes.sort(key=lambda hole: hole.offset)
@@ -195,8 +245,9 @@ def _emit_global_offset_table(self) -> None:
195245
if value_part and not symbol and not addend:
196246
addend_part = ""
197247
else:
248+
signed = "+" if symbol is not None else ""
198249
addend_part = f"&{symbol}" if symbol else ""
199-
addend_part += _format_addend(addend, signed=symbol is not None)
250+
addend_part += f"{_signed(addend):{signed}#x}"
200251
if value_part:
201252
value_part += "+"
202253
self.data.disassembly.append(
@@ -220,8 +271,8 @@ def symbol_to_value(symbol: str) -> tuple[HoleValue, str | None]:
220271
return HoleValue.ZERO, symbol
221272

222273

223-
def _format_addend(addend: int, signed: bool = False) -> str:
224-
addend %= 1 << 64
225-
if addend & (1 << 63):
226-
addend -= 1 << 64
227-
return f"{addend:{'+#x' if signed else '#x'}}"
274+
def _signed(value: int) -> int:
275+
value %= 1 << 64
276+
if value & (1 << 63):
277+
value -= 1 << 64
278+
return value

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy