Skip to content

Commit 49dfb0a

Browse files
committed
[GR-46064] Mark indirect branch targets and emit endbranch
PullRequest: graal/14733
2 parents 39183ff + f8a1814 commit 49dfb0a

File tree

6 files changed

+121
-0
lines changed

6 files changed

+121
-0
lines changed

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4874,6 +4874,13 @@ public final void call(Register src) {
48744874
emitModRM(2, src);
48754875
}
48764876

4877+
public final void endbranch() {
4878+
emitByte(0xf3);
4879+
emitByte(0x0f);
4880+
emitByte(0x1e);
4881+
emitByte(0xfa);
4882+
}
4883+
48774884
public final void int3() {
48784885
emitByte(0xCC);
48794886
}

compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/core/common/cfg/BasicBlock.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ public abstract class BasicBlock<T extends BasicBlock<T>> {
8888
* See {@link #domNumber} for details.
8989
*/
9090
private int maxChildDomNumber = INVALID_BLOCK_ID;
91+
/**
92+
* Indicates if this block is a target of an indirect branch.
93+
*/
94+
private boolean indirectBranchTarget = false;
9195
protected final AbstractControlFlowGraph<T> cfg;
9296

9397
protected BasicBlock(AbstractControlFlowGraph<T> cfg) {
@@ -235,6 +239,14 @@ public final boolean strictlyDominates(BasicBlock<T> other) {
235239
return AbstractControlFlowGraph.strictlyDominates(this, other);
236240
}
237241

242+
public void setIndirectBranchTarget() {
243+
this.indirectBranchTarget = true;
244+
}
245+
246+
public boolean isIndirectBranchTarget() {
247+
return this.indirectBranchTarget;
248+
}
249+
238250
@Override
239251
public String toString() {
240252
return "B" + id;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package org.graalvm.compiler.lir.amd64;
26+
27+
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
28+
import org.graalvm.compiler.lir.LIRInstruction;
29+
import org.graalvm.compiler.lir.LIRInstructionClass;
30+
import org.graalvm.compiler.lir.Opcode;
31+
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
32+
33+
@Opcode("ENDBR64")
34+
public final class EndbranchOp extends AMD64LIRInstruction {
35+
public static final LIRInstructionClass<EndbranchOp> TYPE = LIRInstructionClass.create(EndbranchOp.class);
36+
37+
private EndbranchOp() {
38+
super(TYPE);
39+
}
40+
41+
@Override
42+
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
43+
masm.endbranch();
44+
}
45+
46+
public static LIRInstruction create() {
47+
return new EndbranchOp();
48+
}
49+
50+
}

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1212
* (GR-46392) Add build resources section to the build output that shows the memory and thread limits of the build process.
1313
* (GR-38994) Together with Red Hat, we added support for `-XX:+HeapDumpOnOutOfMemoryError`.
1414
* (GR-47365) Throw `MissingReflectionRegistrationError` when attempting to create a proxy class without having it registered at build-time, instead of a `VMError`.
15+
* (GR-46064) Add option `-H:±IndirectBranchTargetMarker` to mark indirect branch targets on AMD64 with an endbranch instruction. This is a prerequisite for future Intel CET support.
1516

1617
## Version 23.0.0
1718
* (GR-40187) Report invalid use of SVM specific classes on image class- or module-path as error. As a temporary workaround, `-H:+AllowDeprecatedBuilderClassesOnImageClasspath` allows turning the error into a warning.

substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
import java.util.Collection;
4141
import java.util.EnumSet;
42+
import java.util.List;
4243
import java.util.function.BiConsumer;
4344

4445
import org.graalvm.compiler.asm.Label;
@@ -78,6 +79,7 @@
7879
import org.graalvm.compiler.lir.LabelRef;
7980
import org.graalvm.compiler.lir.Opcode;
8081
import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
82+
import org.graalvm.compiler.lir.StandardOp.LabelOp;
8183
import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
8284
import org.graalvm.compiler.lir.Variable;
8385
import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
@@ -94,6 +96,7 @@
9496
import org.graalvm.compiler.lir.amd64.AMD64ReadProcid;
9597
import org.graalvm.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid;
9698
import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper;
99+
import org.graalvm.compiler.lir.amd64.EndbranchOp;
97100
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
98101
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
99102
import org.graalvm.compiler.lir.asm.DataBuilder;
@@ -119,6 +122,7 @@
119122
import org.graalvm.compiler.nodes.SafepointNode;
120123
import org.graalvm.compiler.nodes.StructuredGraph;
121124
import org.graalvm.compiler.nodes.ValueNode;
125+
import org.graalvm.compiler.nodes.cfg.HIRBlock;
122126
import org.graalvm.compiler.nodes.spi.CoreProviders;
123127
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
124128
import org.graalvm.compiler.nodes.spi.NodeValueMap;
@@ -127,6 +131,7 @@
127131
import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase;
128132
import org.graalvm.compiler.phases.util.Providers;
129133
import org.graalvm.compiler.replacements.amd64.AMD64IntrinsicStubs;
134+
import org.graalvm.nativeimage.ImageInfo;
130135
import org.graalvm.nativeimage.ImageSingletons;
131136

132137
import com.oracle.svm.core.CPUFeatureAccess;
@@ -756,6 +761,24 @@ public int getArrayLengthOffset() {
756761
public Register getHeapBaseRegister() {
757762
return ReservedRegisters.singleton().getHeapBaseRegister();
758763
}
764+
765+
@Override
766+
protected void emitRangeTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, AllocatableValue key) {
767+
super.emitRangeTableSwitch(lowKey, defaultTarget, targets, key);
768+
markIndirectBranchTargets(targets);
769+
}
770+
771+
@Override
772+
protected void emitHashTableSwitch(JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, AllocatableValue value, Value hash) {
773+
super.emitHashTableSwitch(keys, defaultTarget, targets, value, hash);
774+
markIndirectBranchTargets(targets);
775+
}
776+
777+
private void markIndirectBranchTargets(LabelRef[] labels) {
778+
for (LabelRef label : labels) {
779+
label.getTargetBlock().setIndirectBranchTarget();
780+
}
781+
}
759782
}
760783

761784
public class SubstrateAMD64NodeLIRBuilder extends AMD64NodeLIRBuilder implements SubstrateNodeLIRBuilder {
@@ -764,6 +787,16 @@ public SubstrateAMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen,
764787
super(graph, gen, nodeMatchRules);
765788
}
766789

790+
@Override
791+
public void doBlockPrologue(@SuppressWarnings("unused") HIRBlock block, @SuppressWarnings("unused") OptionValues options) {
792+
if (SubstrateOptions.IndirectBranchTargetMarker.getValue() && block.isIndirectBranchTarget()) {
793+
List<LIRInstruction> lir = gen.getResult().getLIR().getLIRforBlock(block);
794+
GraalError.guarantee(lir.size() == 1 && lir.get(0) instanceof LabelOp, "block may only contain an initial LabelOp before emitting endbranch");
795+
gen.append(EndbranchOp.create());
796+
}
797+
super.doBlockPrologue(block, options);
798+
}
799+
767800
@Override
768801
public void visitSafepointNode(SafepointNode node) {
769802
throw shouldNotReachHere("handled by lowering");
@@ -999,7 +1032,22 @@ public void enter(CompilationResultBuilder crb) {
9991032
crb.recordMark(PROLOGUE_END);
10001033
}
10011034

1035+
protected void emitEndBranch(CompilationResultBuilder crb) {
1036+
/*
1037+
* Emit an endbranch instruction if we are runtime compiling or the method can be
1038+
* dynamically bound.
1039+
*/
1040+
if (SubstrateOptions.IndirectBranchTargetMarker.getValue() && (ImageInfo.inImageRuntimeCode() || !method.canBeStaticallyBound())) {
1041+
((AMD64Assembler) crb.asm).endbranch();
1042+
}
1043+
}
1044+
10021045
protected void makeFrame(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
1046+
emitEndBranch(crb);
1047+
reserveStackFrame(crb, asm);
1048+
}
1049+
1050+
protected final void reserveStackFrame(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
10031051
maybePushBasePointer(crb, asm);
10041052
asm.decrementq(rsp, crb.frameMap.frameSize());
10051053
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,4 +932,7 @@ public Boolean getValueOrDefault(UnmodifiableEconomicMap<OptionKey<?>, Object> v
932932

933933
@Option(help = "Allows the addresses of pinned objects to be passed to other code.", type = OptionType.Expert) //
934934
public static final HostedOptionKey<Boolean> PinnedObjectAddressing = new HostedOptionKey<>(true);
935+
936+
@Option(help = "Emit indirect branch target marker instructions.", type = OptionType.Expert) //
937+
public static final HostedOptionKey<Boolean> IndirectBranchTargetMarker = new HostedOptionKey<>(false);
935938
}

0 commit comments

Comments
 (0)