@@ -181,6 +181,7 @@ class Stencil:
181
181
body : bytearray = dataclasses .field (default_factory = bytearray , init = False )
182
182
holes : list [Hole ] = dataclasses .field (default_factory = list , init = False )
183
183
disassembly : list [str ] = dataclasses .field (default_factory = list , init = False )
184
+ trampolines : dict [str , int ] = dataclasses .field (default_factory = dict , init = False )
184
185
185
186
def pad (self , alignment : int ) -> None :
186
187
"""Pad the stencil to the given alignment."""
@@ -189,14 +190,25 @@ def pad(self, alignment: int) -> None:
189
190
self .disassembly .append (f"{ offset :x} : { ' ' .join (['00' ] * padding )} " )
190
191
self .body .extend ([0 ] * padding )
191
192
192
- def emit_aarch64_trampoline (self , hole : Hole ) -> None :
193
+ def emit_aarch64_trampoline (self , hole : Hole , alignment : int ) -> None :
193
194
"""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 )
195
203
where = slice (hole .offset , hole .offset + 4 )
196
204
instruction = int .from_bytes (self .body [where ], sys .byteorder )
197
205
instruction &= 0xFC000000
198
206
instruction |= ((base - hole .offset ) >> 2 ) & 0x03FFFFFF
199
207
self .body [where ] = instruction .to_bytes (4 , sys .byteorder )
208
+
209
+ if reuse_trampoline :
210
+ return
211
+
200
212
self .disassembly += [
201
213
f"{ base + 4 * 0 :x} : d2800008 mov x8, #0x0" ,
202
214
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:
225
237
]
226
238
):
227
239
self .holes .append (hole .replace (offset = base + 4 * i , kind = kind ))
240
+ self .trampolines [hole .symbol ] = base
228
241
229
242
def remove_jump (self , * , alignment : int = 1 ) -> None :
230
243
"""Remove a zero-length continuation jump, if it exists."""
@@ -300,8 +313,7 @@ def process_relocations(self, *, alignment: int = 1) -> None:
300
313
in {"R_AARCH64_CALL26" , "R_AARCH64_JUMP26" , "ARM64_RELOC_BRANCH26" }
301
314
and hole .value is HoleValue .ZERO
302
315
):
303
- self .code .pad (alignment )
304
- self .code .emit_aarch64_trampoline (hole )
316
+ self .code .emit_aarch64_trampoline (hole , alignment )
305
317
self .code .holes .remove (hole )
306
318
self .code .remove_jump (alignment = alignment )
307
319
self .code .pad (alignment )
0 commit comments