@@ -181,6 +181,7 @@ class Stencil:
181181 body : bytearray = dataclasses .field (default_factory = bytearray , init = False )
182182 holes : list [Hole ] = dataclasses .field (default_factory = list , init = False )
183183 disassembly : list [str ] = dataclasses .field (default_factory = list , init = False )
184+ trampolines : dict [str , int ] = dataclasses .field (default_factory = dict , init = False )
184185
185186 def pad (self , alignment : int ) -> None :
186187 """Pad the stencil to the given alignment."""
@@ -189,14 +190,25 @@ def pad(self, alignment: int) -> None:
189190 self .disassembly .append (f"{ offset :x} : { ' ' .join (['00' ] * padding )} " )
190191 self .body .extend ([0 ] * padding )
191192
192- def emit_aarch64_trampoline (self , hole : Hole ) -> None :
193+ def emit_aarch64_trampoline (self , hole : Hole , alignment : int ) -> None :
193194 """Even with the large code model, AArch64 Linux insists on 28-bit jumps."""
194- base = len (self .body )
195+ assert hole .symbol is not None
196+ reuse_trampoline = hole .symbol in self .trampolines
197+ if reuse_trampoline :
198+ # Re-use the base address of the previously created trampoline
199+ base = self .trampolines [hole .symbol ]
200+ else :
201+ self .pad (alignment )
202+ base = len (self .body )
195203 where = slice (hole .offset , hole .offset + 4 )
196204 instruction = int .from_bytes (self .body [where ], sys .byteorder )
197205 instruction &= 0xFC000000
198206 instruction |= ((base - hole .offset ) >> 2 ) & 0x03FFFFFF
199207 self .body [where ] = instruction .to_bytes (4 , sys .byteorder )
208+
209+ if reuse_trampoline :
210+ return
211+
200212 self .disassembly += [
201213 f"{ base + 4 * 0 :x} : d2800008 mov x8, #0x0" ,
202214 f"{ base + 4 * 0 :016x} : R_AARCH64_MOVW_UABS_G0_NC { hole .symbol } " ,
@@ -225,6 +237,7 @@ def emit_aarch64_trampoline(self, hole: Hole) -> None:
225237 ]
226238 ):
227239 self .holes .append (hole .replace (offset = base + 4 * i , kind = kind ))
240+ self .trampolines [hole .symbol ] = base
228241
229242 def remove_jump (self , * , alignment : int = 1 ) -> None :
230243 """Remove a zero-length continuation jump, if it exists."""
@@ -300,8 +313,7 @@ def process_relocations(self, *, alignment: int = 1) -> None:
300313 in {"R_AARCH64_CALL26" , "R_AARCH64_JUMP26" , "ARM64_RELOC_BRANCH26" }
301314 and hole .value is HoleValue .ZERO
302315 ):
303- self .code .pad (alignment )
304- self .code .emit_aarch64_trampoline (hole )
316+ self .code .emit_aarch64_trampoline (hole , alignment )
305317 self .code .holes .remove (hole )
306318 self .code .remove_jump (alignment = alignment )
307319 self .code .pad (alignment )
0 commit comments