52
52
import org .graalvm .nativeimage .Platforms ;
53
53
import org .graalvm .word .Pointer ;
54
54
55
+ import com .oracle .svm .core .BuildPhaseProvider .AfterAnalysis ;
56
+ import com .oracle .svm .core .SubstrateControlFlowIntegrity ;
55
57
import com .oracle .svm .core .SubstrateTargetDescription ;
56
58
import com .oracle .svm .core .aarch64 .SubstrateAArch64MacroAssembler ;
57
59
import com .oracle .svm .core .config .ConfigurationValues ;
58
60
import com .oracle .svm .core .foreign .AbiUtils .Adapter .Adaptation ;
59
61
import com .oracle .svm .core .graal .code .AssignedLocation ;
62
+ import com .oracle .svm .core .graal .code .SubstrateBackendWithAssembler ;
60
63
import com .oracle .svm .core .headers .LibC ;
61
64
import com .oracle .svm .core .headers .WindowsAPIs ;
65
+ import com .oracle .svm .core .heap .UnknownPrimitiveField ;
62
66
import com .oracle .svm .core .util .BasedOnJDKClass ;
63
67
import com .oracle .svm .core .util .BasedOnJDKFile ;
64
68
import com .oracle .svm .core .util .VMError ;
69
73
import jdk .graal .compiler .asm .aarch64 .AArch64Address ;
70
74
import jdk .graal .compiler .asm .aarch64 .AArch64MacroAssembler ;
71
75
import jdk .graal .compiler .asm .amd64 .AMD64Address ;
72
- import jdk .graal .compiler .asm .amd64 .AMD64Assembler ;
73
76
import jdk .graal .compiler .asm .amd64 .AMD64BaseAssembler ;
77
+ import jdk .graal .compiler .asm .amd64 .AMD64MacroAssembler ;
74
78
import jdk .graal .compiler .graph .Node ;
75
79
import jdk .graal .compiler .nodes .ValueNode ;
76
80
import jdk .graal .compiler .nodes .calc .AddNode ;
@@ -671,11 +675,40 @@ public record Registers(Register methodHandle, Register isolate) {
671
675
672
676
public abstract int trampolineSize ();
673
677
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
+
675
707
public Pointer write (Pointer at , Isolate isolate , Word methodHandle , Word stubPointer ) {
676
708
for (int i = 0 ; i < assemblyTemplate .length ; ++i ) {
677
709
at .writeByte (i , assemblyTemplate [i ]);
678
710
}
711
+
679
712
at .writeWord (isolateOffset , isolate );
680
713
at .writeWord (methodHandleOffset , methodHandle );
681
714
at .writeWord (stubOffset , stubPointer );
@@ -685,7 +718,7 @@ public Pointer write(Pointer at, Isolate isolate, Word methodHandle, Word stubPo
685
718
}
686
719
687
720
@ Platforms (Platform .HOSTED_ONLY .class )
688
- abstract TrampolineTemplate generateTrampolineTemplate ();
721
+ abstract void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template );
689
722
}
690
723
691
724
class ABIs {
@@ -740,8 +773,8 @@ public int trampolineSize() {
740
773
}
741
774
742
775
@ Override
743
- public TrampolineTemplate generateTrampolineTemplate () {
744
- return null ;
776
+ public void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template ) {
777
+ fail () ;
745
778
}
746
779
747
780
@ Override
@@ -812,8 +845,8 @@ public int trampolineSize() {
812
845
813
846
@ Platforms (Platform .HOSTED_ONLY .class )
814
847
@ 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 ( );
817
850
818
851
Register mhRegister = upcallSpecialArgumentsRegisters ().methodHandle ();
819
852
Register isolateRegister = upcallSpecialArgumentsRegisters ().isolate ();
@@ -849,12 +882,11 @@ public TrampolineTemplate generateTrampolineTemplate() {
849
882
masm .jmp (scratch );
850
883
851
884
assert trampolineSize () >= masm .position ();
852
- masm .align (trampolineSize ());
853
885
854
- byte [] assembly = masm .close (true );
886
+ byte [] assembly = masm .closeAligned (true , trampolineSize () );
855
887
assert assembly .length == trampolineSize ();
856
888
857
- return new TrampolineTemplate (assembly , posIsolate , posMHArray , posCallTarget );
889
+ template . setTemplate (assembly , posIsolate , posMHArray , posCallTarget );
858
890
}
859
891
860
892
@ 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() {
974
1006
975
1007
@ Platforms (Platform .HOSTED_ONLY .class )
976
1008
@ Override
977
- public TrampolineTemplate generateTrampolineTemplate () {
1009
+ public void generateTrampolineTemplate (SubstrateBackendWithAssembler <?> backend , TrampolineTemplate template ) {
978
1010
// Generate the trampoline
979
- AMD64Assembler asm = new AMD64Assembler ( ConfigurationValues . getTarget () );
1011
+ AMD64MacroAssembler asm = ( AMD64MacroAssembler ) backend . createAssemblerNoOptions ( );
980
1012
var odas = new ArrayList <AMD64BaseAssembler .OperandDataAnnotation >(3 );
981
1013
// Collect the positions of the address in the movq instructions.
982
1014
asm .setCodePatchingAnnotationConsumer (ca -> {
@@ -988,6 +1020,7 @@ public TrampolineTemplate generateTrampolineTemplate() {
988
1020
Register mhRegister = upcallSpecialArgumentsRegisters ().methodHandle ();
989
1021
Register isolateRegister = upcallSpecialArgumentsRegisters ().isolate ();
990
1022
1023
+ asm .maybeEmitIndirectTargetMarker ();
991
1024
/* Store isolate in the assigned register */
992
1025
asm .movq (isolateRegister , 0L , true );
993
1026
/* r10 points in the mh array */
@@ -997,17 +1030,21 @@ public TrampolineTemplate generateTrampolineTemplate() {
997
1030
/* rax contains the stub address */
998
1031
asm .movq (rax , 0L , true );
999
1032
/* 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
+ }
1001
1039
1002
1040
assert trampolineSize () - asm .position () >= 0 ;
1003
- asm .nop (trampolineSize () - asm .position ());
1004
1041
1005
- byte [] assembly = asm .close (true );
1042
+ byte [] assembly = asm .closeAligned (true , trampolineSize () );
1006
1043
assert assembly .length == trampolineSize ();
1007
1044
assert odas .size () == 3 ;
1008
1045
assert odas .stream ().allMatch (oda -> oda .operandSize == 8 );
1009
1046
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 );
1011
1048
}
1012
1049
}
1013
1050
0 commit comments