5252import org .graalvm .nativeimage .Platforms ;
5353import org .graalvm .word .Pointer ;
5454
55+ import com .oracle .svm .core .BuildPhaseProvider .AfterAnalysis ;
56+ import com .oracle .svm .core .SubstrateControlFlowIntegrity ;
5557import com .oracle .svm .core .SubstrateTargetDescription ;
5658import com .oracle .svm .core .aarch64 .SubstrateAArch64MacroAssembler ;
5759import com .oracle .svm .core .config .ConfigurationValues ;
5860import com .oracle .svm .core .foreign .AbiUtils .Adapter .Adaptation ;
5961import com .oracle .svm .core .graal .code .AssignedLocation ;
62+ import com .oracle .svm .core .graal .code .SubstrateBackendWithAssembler ;
6063import com .oracle .svm .core .headers .LibC ;
6164import com .oracle .svm .core .headers .WindowsAPIs ;
65+ import com .oracle .svm .core .heap .UnknownPrimitiveField ;
6266import com .oracle .svm .core .util .BasedOnJDKClass ;
6367import com .oracle .svm .core .util .BasedOnJDKFile ;
6468import com .oracle .svm .core .util .VMError ;
6973import jdk .graal .compiler .asm .aarch64 .AArch64Address ;
7074import jdk .graal .compiler .asm .aarch64 .AArch64MacroAssembler ;
7175import jdk .graal .compiler .asm .amd64 .AMD64Address ;
72- import jdk .graal .compiler .asm .amd64 .AMD64Assembler ;
7376import jdk .graal .compiler .asm .amd64 .AMD64BaseAssembler ;
77+ import jdk .graal .compiler .asm .amd64 .AMD64MacroAssembler ;
7478import jdk .graal .compiler .graph .Node ;
7579import jdk .graal .compiler .nodes .ValueNode ;
7680import jdk .graal .compiler .nodes .calc .AddNode ;
@@ -671,11 +675,40 @@ public record Registers(Register methodHandle, Register isolate) {
671675
672676 public abstract int trampolineSize ();
673677
674- record TrampolineTemplate (byte [] assemblyTemplate , int isolateOffset , int methodHandleOffset , int stubOffset ) {
678+ public static class TrampolineTemplate {
679+
680+ private final byte [] assemblyTemplate ;
681+
682+ /*
683+ * These fields will only be filled after the analysis, when an assembler is available.
684+ * Prevent optimizations that constant-fold these fields already during analysis.
685+ */
686+
687+ @ UnknownPrimitiveField (availability = AfterAnalysis .class ) //
688+ private int isolateOffset ;
689+ @ UnknownPrimitiveField (availability = AfterAnalysis .class ) //
690+ private int methodHandleOffset ;
691+ @ UnknownPrimitiveField (availability = AfterAnalysis .class ) //
692+ private int stubOffset ;
693+
694+ public TrampolineTemplate (byte [] assemblyTemplate ) {
695+ this .assemblyTemplate = assemblyTemplate ;
696+ }
697+
698+ @ Platforms (Platform .HOSTED_ONLY .class )
699+ public void setTemplate (byte [] code , int isolateOff , int methodHandleOff , int stubOff ) {
700+ assert code .length == this .assemblyTemplate .length ;
701+ System .arraycopy (code , 0 , this .assemblyTemplate , 0 , this .assemblyTemplate .length );
702+ this .isolateOffset = isolateOff ;
703+ this .methodHandleOffset = methodHandleOff ;
704+ this .stubOffset = stubOff ;
705+ }
706+
675707 public Pointer write (Pointer at , Isolate isolate , Word methodHandle , Word stubPointer ) {
676708 for (int i = 0 ; i < assemblyTemplate .length ; ++i ) {
677709 at .writeByte (i , assemblyTemplate [i ]);
678710 }
711+
679712 at .writeWord (isolateOffset , isolate );
680713 at .writeWord (methodHandleOffset , methodHandle );
681714 at .writeWord (stubOffset , stubPointer );
@@ -685,7 +718,7 @@ public Pointer write(Pointer at, Isolate isolate, Word methodHandle, Word stubPo
685718 }
686719
687720 @ Platforms (Platform .HOSTED_ONLY .class )
688- abstract TrampolineTemplate generateTrampolineTemplate ();
721+ abstract void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template );
689722}
690723
691724class ABIs {
@@ -740,8 +773,8 @@ public int trampolineSize() {
740773 }
741774
742775 @ Override
743- public TrampolineTemplate generateTrampolineTemplate () {
744- return null ;
776+ public void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template ) {
777+ fail () ;
745778 }
746779
747780 @ Override
@@ -812,8 +845,8 @@ public int trampolineSize() {
812845
813846 @ Platforms (Platform .HOSTED_ONLY .class )
814847 @ Override
815- public TrampolineTemplate generateTrampolineTemplate () {
816- AArch64MacroAssembler masm = new SubstrateAArch64MacroAssembler ( ConfigurationValues . getTarget () );
848+ public void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template ) {
849+ AArch64MacroAssembler masm = ( AArch64MacroAssembler ) backend . createAssemblerNoOptions ( );
817850
818851 Register mhRegister = upcallSpecialArgumentsRegisters ().methodHandle ();
819852 Register isolateRegister = upcallSpecialArgumentsRegisters ().isolate ();
@@ -849,12 +882,11 @@ public TrampolineTemplate generateTrampolineTemplate() {
849882 masm .jmp (scratch );
850883
851884 assert trampolineSize () >= masm .position ();
852- masm .align (trampolineSize ());
853885
854- byte [] assembly = masm .close (true );
886+ byte [] assembly = masm .closeAligned (true , trampolineSize () );
855887 assert assembly .length == trampolineSize ();
856888
857- return new TrampolineTemplate (assembly , posIsolate , posMHArray , posCallTarget );
889+ template . setTemplate (assembly , posIsolate , posMHArray , posCallTarget );
858890 }
859891
860892 @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+13/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java#L195" )
@@ -974,9 +1006,9 @@ public int trampolineSize() {
9741006
9751007 @ Platforms (Platform .HOSTED_ONLY .class )
9761008 @ Override
977- public TrampolineTemplate generateTrampolineTemplate () {
1009+ public void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template ) {
9781010 // Generate the trampoline
979- AMD64Assembler asm = new AMD64Assembler ( ConfigurationValues . getTarget () );
1011+ AMD64MacroAssembler asm = ( AMD64MacroAssembler ) backend . createAssemblerNoOptions ( );
9801012 var odas = new ArrayList <AMD64BaseAssembler .OperandDataAnnotation >(3 );
9811013 // Collect the positions of the address in the movq instructions.
9821014 asm .setCodePatchingAnnotationConsumer (ca -> {
@@ -988,6 +1020,7 @@ public TrampolineTemplate generateTrampolineTemplate() {
9881020 Register mhRegister = upcallSpecialArgumentsRegisters ().methodHandle ();
9891021 Register isolateRegister = upcallSpecialArgumentsRegisters ().isolate ();
9901022
1023+ asm .maybeEmitIndirectTargetMarker ();
9911024 /* Store isolate in the assigned register */
9921025 asm .movq (isolateRegister , 0L , true );
9931026 /* r10 points in the mh array */
@@ -997,17 +1030,21 @@ public TrampolineTemplate generateTrampolineTemplate() {
9971030 /* rax contains the stub address */
9981031 asm .movq (rax , 0L , true );
9991032 /* executes the stub */
1000- asm .jmp (new AMD64Address (rax , 0 ));
1033+ if (SubstrateControlFlowIntegrity .useSoftwareCFI ()) {
1034+ asm .movq (rax , new AMD64Address (rax , 0 ));
1035+ asm .jmp (rax );
1036+ } else {
1037+ asm .jmp (new AMD64Address (rax , 0 ));
1038+ }
10011039
10021040 assert trampolineSize () - asm .position () >= 0 ;
1003- asm .nop (trampolineSize () - asm .position ());
10041041
1005- byte [] assembly = asm .close (true );
1042+ byte [] assembly = asm .closeAligned (true , trampolineSize () );
10061043 assert assembly .length == trampolineSize ();
10071044 assert odas .size () == 3 ;
10081045 assert odas .stream ().allMatch (oda -> oda .operandSize == 8 );
10091046
1010- return new TrampolineTemplate (assembly , odas .get (0 ).operandPosition , odas .get (1 ).operandPosition , odas .get (2 ).operandPosition );
1047+ template . setTemplate (assembly , odas .get (0 ).operandPosition , odas .get (1 ).operandPosition , odas .get (2 ).operandPosition );
10111048 }
10121049 }
10131050
0 commit comments