@@ -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
129179class 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