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)