Skip to content

Commit

Permalink
[GR-46064] Mark indirect branch targets and emit endbranch
Browse files Browse the repository at this point in the history
PullRequest: graal/14733
  • Loading branch information
matneu committed Aug 7, 2023
2 parents 39183ff + f8a1814 commit 49dfb0a
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4874,6 +4874,13 @@ public final void call(Register src) {
emitModRM(2, src);
}

public final void endbranch() {
emitByte(0xf3);
emitByte(0x0f);
emitByte(0x1e);
emitByte(0xfa);
}

public final void int3() {
emitByte(0xCC);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ public abstract class BasicBlock<T extends BasicBlock<T>> {
* See {@link #domNumber} for details.
*/
private int maxChildDomNumber = INVALID_BLOCK_ID;
/**
* Indicates if this block is a target of an indirect branch.
*/
private boolean indirectBranchTarget = false;
protected final AbstractControlFlowGraph<T> cfg;

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

public void setIndirectBranchTarget() {
this.indirectBranchTarget = true;
}

public boolean isIndirectBranchTarget() {
return this.indirectBranchTarget;
}

@Override
public String toString() {
return "B" + id;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.lir.amd64;

import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;

@Opcode("ENDBR64")
public final class EndbranchOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<EndbranchOp> TYPE = LIRInstructionClass.create(EndbranchOp.class);

private EndbranchOp() {
super(TYPE);
}

@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
masm.endbranch();
}

public static LIRInstruction create() {
return new EndbranchOp();
}

}
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-46392) Add build resources section to the build output that shows the memory and thread limits of the build process.
* (GR-38994) Together with Red Hat, we added support for `-XX:+HeapDumpOnOutOfMemoryError`.
* (GR-47365) Throw `MissingReflectionRegistrationError` when attempting to create a proxy class without having it registered at build-time, instead of a `VMError`.
* (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.

## Version 23.0.0
* (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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.function.BiConsumer;

import org.graalvm.compiler.asm.Label;
Expand Down Expand Up @@ -78,6 +79,7 @@
import org.graalvm.compiler.lir.LabelRef;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
import org.graalvm.compiler.lir.StandardOp.LabelOp;
import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
Expand All @@ -94,6 +96,7 @@
import org.graalvm.compiler.lir.amd64.AMD64ReadProcid;
import org.graalvm.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid;
import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper;
import org.graalvm.compiler.lir.amd64.EndbranchOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.asm.DataBuilder;
Expand All @@ -119,6 +122,7 @@
import org.graalvm.compiler.nodes.SafepointNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.cfg.HIRBlock;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.spi.NodeValueMap;
Expand All @@ -127,6 +131,7 @@
import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.amd64.AMD64IntrinsicStubs;
import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.CPUFeatureAccess;
Expand Down Expand Up @@ -756,6 +761,24 @@ public int getArrayLengthOffset() {
public Register getHeapBaseRegister() {
return ReservedRegisters.singleton().getHeapBaseRegister();
}

@Override
protected void emitRangeTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, AllocatableValue key) {
super.emitRangeTableSwitch(lowKey, defaultTarget, targets, key);
markIndirectBranchTargets(targets);
}

@Override
protected void emitHashTableSwitch(JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, AllocatableValue value, Value hash) {
super.emitHashTableSwitch(keys, defaultTarget, targets, value, hash);
markIndirectBranchTargets(targets);
}

private void markIndirectBranchTargets(LabelRef[] labels) {
for (LabelRef label : labels) {
label.getTargetBlock().setIndirectBranchTarget();
}
}
}

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

@Override
public void doBlockPrologue(@SuppressWarnings("unused") HIRBlock block, @SuppressWarnings("unused") OptionValues options) {
if (SubstrateOptions.IndirectBranchTargetMarker.getValue() && block.isIndirectBranchTarget()) {
List<LIRInstruction> lir = gen.getResult().getLIR().getLIRforBlock(block);
GraalError.guarantee(lir.size() == 1 && lir.get(0) instanceof LabelOp, "block may only contain an initial LabelOp before emitting endbranch");
gen.append(EndbranchOp.create());
}
super.doBlockPrologue(block, options);
}

@Override
public void visitSafepointNode(SafepointNode node) {
throw shouldNotReachHere("handled by lowering");
Expand Down Expand Up @@ -999,7 +1032,22 @@ public void enter(CompilationResultBuilder crb) {
crb.recordMark(PROLOGUE_END);
}

protected void emitEndBranch(CompilationResultBuilder crb) {
/*
* Emit an endbranch instruction if we are runtime compiling or the method can be
* dynamically bound.
*/
if (SubstrateOptions.IndirectBranchTargetMarker.getValue() && (ImageInfo.inImageRuntimeCode() || !method.canBeStaticallyBound())) {
((AMD64Assembler) crb.asm).endbranch();
}
}

protected void makeFrame(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
emitEndBranch(crb);
reserveStackFrame(crb, asm);
}

protected final void reserveStackFrame(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
maybePushBasePointer(crb, asm);
asm.decrementq(rsp, crb.frameMap.frameSize());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -932,4 +932,7 @@ public Boolean getValueOrDefault(UnmodifiableEconomicMap<OptionKey<?>, Object> v

@Option(help = "Allows the addresses of pinned objects to be passed to other code.", type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> PinnedObjectAddressing = new HostedOptionKey<>(true);

@Option(help = "Emit indirect branch target marker instructions.", type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> IndirectBranchTargetMarker = new HostedOptionKey<>(false);
}

0 comments on commit 49dfb0a

Please sign in to comment.