@@ -63,7 +63,7 @@ def as_c(self) -> str:
63
63
f"HoleKind_{ self .kind } " ,
64
64
f"HoleValue_{ self .value .name } " ,
65
65
f"&{ self .symbol } " if self .symbol else "NULL" ,
66
- _format_addend (self .addend ),
66
+ f" { _signed (self .addend ):#x } " ,
67
67
]
68
68
return f"{{{ ', ' .join (parts )} }}"
69
69
@@ -124,6 +124,56 @@ def emit_aarch64_trampoline(self, hole: Hole) -> None:
124
124
):
125
125
self .holes .append (hole .replace (offset = base + 4 * i , kind = kind ))
126
126
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
+
127
177
128
178
@dataclasses .dataclass
129
179
class StencilGroup :
@@ -142,10 +192,19 @@ class StencilGroup:
142
192
143
193
def process_relocations (self , * , alignment : int = 1 ) -> None :
144
194
"""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 ()
145
205
self .code .pad (alignment )
146
206
self .data .pad (8 )
147
207
for stencil in [self .code , self .data ]:
148
- holes = []
149
208
for hole in stencil .holes :
150
209
if hole .value is HoleValue .GOT :
151
210
assert hole .symbol is not None
@@ -156,22 +215,13 @@ def process_relocations(self, *, alignment: int = 1) -> None:
156
215
hole .value , addend = self .symbols [hole .symbol ]
157
216
hole .addend += addend
158
217
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
165
218
elif (
166
219
hole .kind in {"IMAGE_REL_AMD64_REL32" }
167
220
and hole .value is HoleValue .ZERO
168
221
):
169
222
raise ValueError (
170
223
f"Add PyAPI_FUNC(...) or PyAPI_DATA(...) to declaration of { hole .symbol } !"
171
224
)
172
- holes .append (hole )
173
- stencil .holes [:] = holes
174
- self .code .pad (alignment )
175
225
self ._emit_global_offset_table ()
176
226
self .code .holes .sort (key = lambda hole : hole .offset )
177
227
self .data .holes .sort (key = lambda hole : hole .offset )
@@ -195,8 +245,9 @@ def _emit_global_offset_table(self) -> None:
195
245
if value_part and not symbol and not addend :
196
246
addend_part = ""
197
247
else :
248
+ signed = "+" if symbol is not None else ""
198
249
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 } "
200
251
if value_part :
201
252
value_part += "+"
202
253
self .data .disassembly .append (
@@ -220,8 +271,8 @@ def symbol_to_value(symbol: str) -> tuple[HoleValue, str | None]:
220
271
return HoleValue .ZERO , symbol
221
272
222
273
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