Skip to content

Commit 64389bc

Browse files
committed
[GR-33875] Fail when invoking invalid method pointers.
PullRequest: graal/10000
2 parents 55ab7d5 + 3146957 commit 64389bc

File tree

14 files changed

+76
-55
lines changed

14 files changed

+76
-55
lines changed

substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ private void linkCompiledBatches(BatchExecutor executor, DebugContext debug, int
207207
stackMapDumper.close();
208208

209209
HostedMethod firstMethod = (HostedMethod) getFirstCompilation().getMethods()[0];
210-
buildRuntimeMetadata(MethodPointer.factory(firstMethod), WordFactory.signed(textSectionInfo.getCodeSize()));
210+
buildRuntimeMetadata(new MethodPointer(firstMethod), WordFactory.signed(textSectionInfo.getCodeSize()));
211211
}
212212

213213
private void llvmOptimize(DebugContext debug, String outputPath, String inputPath) {
Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,33 @@
4343
import com.oracle.svm.util.ReflectionUtil;
4444

4545
/**
46-
* Provides a stub method that can be used to fill otherwise unused vtable slots. Instead of a
47-
* segfault, this method provides a full diagnostic output with a stack trace.
46+
* Provides stub methods that can be used for uninitialized method pointers. Instead of a segfault,
47+
* the stubs provide full diagnostic output with a stack trace.
4848
*/
49-
public final class InvalidVTableEntryHandler {
50-
public static final Method HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidVTableEntryHandler.class, "invalidVTableEntryHandler");
51-
public static final String MSG = "Fatal error: Virtual method call used an illegal vtable entry that was seen as unused by the static analysis";
49+
public final class InvalidMethodPointerHandler {
50+
public static final Method INVALID_VTABLE_ENTRY_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "invalidVTableEntryHandler");
51+
public static final String INVALID_VTABLE_ENTRY_MSG = "Fatal error: Virtual method call used an illegal vtable entry that was seen as unused by the static analysis";
52+
53+
public static final Method METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD = ReflectionUtil.lookupMethod(InvalidMethodPointerHandler.class, "methodPointerNotCompiledHandler");
54+
public static final String METHOD_POINTER_NOT_COMPILED_MSG = "Fatal error: Method pointer invoked on a method that was not compiled because it was not seen as invoked by the static analysis nor was it directly registered for compilation";
5255

5356
@StubCallingConvention
5457
@NeverInline("We need a separate frame that stores all registers")
5558
private static void invalidVTableEntryHandler() {
59+
Pointer callerSP = KnownIntrinsics.readCallerStackPointer();
60+
CodePointer callerIP = KnownIntrinsics.readReturnAddress();
61+
failFatally(callerSP, callerIP, INVALID_VTABLE_ENTRY_MSG);
62+
}
63+
64+
@StubCallingConvention
65+
@NeverInline("We need a separate frame that stores all registers")
66+
private static void methodPointerNotCompiledHandler() {
67+
Pointer callerSP = KnownIntrinsics.readCallerStackPointer();
68+
CodePointer callerIP = KnownIntrinsics.readReturnAddress();
69+
failFatally(callerSP, callerIP, METHOD_POINTER_NOT_COMPILED_MSG);
70+
}
71+
72+
private static void failFatally(Pointer callerSP, CodePointer callerIP, String message) {
5673
VMThreads.StatusSupport.setStatusIgnoreSafepoints();
5774
StackOverflowCheck.singleton().disableStackOverflowChecksForFatalError();
5875

@@ -63,13 +80,11 @@ private static void invalidVTableEntryHandler() {
6380
* from the method that has the illegal vtable call. That can be helpful when debugging the
6481
* cause of the fatal error.
6582
*/
66-
Pointer callerSP = KnownIntrinsics.readCallerStackPointer();
67-
CodePointer callerIP = KnownIntrinsics.readReturnAddress();
6883
LogHandler logHandler = ImageSingletons.lookup(LogHandler.class);
69-
Log log = Log.enterFatalContext(logHandler, callerIP, MSG, null);
84+
Log log = Log.enterFatalContext(logHandler, callerIP, message, null);
7085
if (log != null) {
7186
SubstrateDiagnostics.printFatalError(log, callerSP, callerIP, WordFactory.nullPointer(), true);
72-
log.string(MSG).newline();
87+
log.string(message).newline();
7388
}
7489
logHandler.fatalError();
7590
}

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/DeoptimizationFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,6 @@ public void beforeCompilation(BeforeCompilationAccess a) {
126126
CompilationAccessImpl config = (CompilationAccessImpl) a;
127127
config.registerAsImmutable(ImageSingletons.lookup(DeoptimizationSupport.class));
128128
HostedMetaAccess metaAccess = config.getMetaAccess();
129-
DeoptimizationSupport.setDeoptStubPointer(MethodPointer.factory(metaAccess.lookupJavaMethod(deoptStubMethod)));
129+
DeoptimizationSupport.setDeoptStubPointer(new MethodPointer(metaAccess.lookupJavaMethod(deoptStubMethod)));
130130
}
131131
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.graalvm.compiler.graph.Node;
4545
import org.graalvm.compiler.options.OptionValues;
4646
import org.graalvm.compiler.phases.util.Providers;
47+
import org.graalvm.nativeimage.c.function.CFunctionPointer;
4748

4849
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
4950
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
@@ -340,7 +341,7 @@ private static ClassInitializationInfo buildRuntimeInitializationInfo(FeatureImp
340341
/* Synthesize a VerifyError to be thrown at run time. */
341342
AnalysisMethod throwVerifyError = access.getMetaAccess().lookupJavaMethod(ExceptionSynthesizer.throwExceptionMethod(VerifyError.class));
342343
access.registerAsCompiled(throwVerifyError);
343-
return new ClassInitializationInfo(MethodPointer.factory(throwVerifyError));
344+
return new ClassInitializationInfo(new MethodPointer(throwVerifyError));
344345
} catch (Throwable t) {
345346
/*
346347
* All other linking errors will be reported as NoClassDefFoundError when initialization
@@ -354,11 +355,13 @@ private static ClassInitializationInfo buildRuntimeInitializationInfo(FeatureImp
354355
* information.
355356
*/
356357
assert type.isLinked();
358+
CFunctionPointer classInitializerFunction = null;
357359
AnalysisMethod classInitializer = type.getClassInitializer();
358360
if (classInitializer != null) {
359361
assert classInitializer.getCode() != null;
360362
access.registerAsCompiled(classInitializer);
363+
classInitializerFunction = new MethodPointer(classInitializer);
361364
}
362-
return new ClassInitializationInfo(MethodPointer.factory(classInitializer));
365+
return new ClassInitializationInfo(classInitializerFunction);
363366
}
364367
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public AnalysisMethod registerJavaStubForMethod(AnalysisMethod method) {
110110
if (value == null) {
111111
assert !bb.getUniverse().sealed();
112112
AnalysisMethod nativeStub = registerStubForMethod(method, () -> CEntryPointData.create(method));
113-
CFunctionPointer nativeStubAddress = MethodPointer.factory(nativeStub);
113+
CFunctionPointer nativeStubAddress = new MethodPointer(nativeStub);
114114
String stubName = SubstrateUtil.uniqueShortName(method);
115115
ResolvedJavaType holderClass = bb.getMetaAccess().lookupJavaType(IsolateLeaveStub.class).getWrapped();
116116
CEntryPointJavaCallStubMethod stub = new CEntryPointJavaCallStubMethod(method.getWrapped(), stubName, holderClass, nativeStubAddress);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointLiteralFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public Object apply(Object source) {
8181
* Only during compilation and native image writing, we do the actual
8282
* replacement.
8383
*/
84-
return MethodPointer.factory(hStub);
84+
return new MethodPointer(hStub);
8585
}
8686
}
8787
return source;

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void layoutMethods(DebugContext debug, String imageName, BigBang bb, Fork
103103
codeCacheSize = NumUtil.roundUp(codeCacheSize + compilation.getTargetCodeSize(), SubstrateOptions.codeAlignment());
104104
}
105105

106-
buildRuntimeMetadata(MethodPointer.factory(firstMethod), WordFactory.unsigned(codeCacheSize));
106+
buildRuntimeMetadata(new MethodPointer(firstMethod), WordFactory.unsigned(codeCacheSize));
107107
}
108108
}
109109

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.graalvm.compiler.debug.Indent;
6060
import org.graalvm.nativeimage.ImageSingletons;
6161
import org.graalvm.nativeimage.c.function.CFunctionPointer;
62+
import org.graalvm.nativeimage.hosted.Feature;
6263

6364
import com.oracle.graal.pointsto.meta.AnalysisMethod;
6465
import com.oracle.graal.pointsto.meta.AnalysisType;
@@ -77,9 +78,11 @@
7778
import com.oracle.svm.core.BuildArtifacts;
7879
import com.oracle.svm.core.BuildArtifacts.ArtifactType;
7980
import com.oracle.svm.core.FrameAccess;
81+
import com.oracle.svm.core.InvalidMethodPointerHandler;
8082
import com.oracle.svm.core.Isolates;
8183
import com.oracle.svm.core.SubstrateOptions;
8284
import com.oracle.svm.core.SubstrateUtil;
85+
import com.oracle.svm.core.annotate.AutomaticFeature;
8386
import com.oracle.svm.core.c.CConst;
8487
import com.oracle.svm.core.c.CGlobalDataImpl;
8588
import com.oracle.svm.core.c.CHeader;
@@ -96,6 +99,7 @@
9699
import com.oracle.svm.core.meta.SubstrateObjectConstant;
97100
import com.oracle.svm.core.option.HostedOptionValues;
98101
import com.oracle.svm.core.util.UserError;
102+
import com.oracle.svm.hosted.FeatureImpl;
99103
import com.oracle.svm.hosted.NativeImageOptions;
100104
import com.oracle.svm.hosted.c.CGlobalDataFeature;
101105
import com.oracle.svm.hosted.c.NativeLibraries;
@@ -564,14 +568,19 @@ private static boolean checkEmbeddedOffset(ProgbitsSectionImpl sectionImpl, fina
564568
return true;
565569
}
566570

567-
private static void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) {
571+
private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) {
568572
assert info.getTargetObject() instanceof CFunctionPointer : "Wrong type for FunctionPointer relocation: " + info.getTargetObject().toString();
569573
final int functionPointerRelocationSize = 8;
570574
assert info.getRelocationSize() == functionPointerRelocationSize : "Function relocation: " + info.getRelocationSize() + " should be " + functionPointerRelocationSize + " bytes.";
571575
// References to functions are via relocations to the symbol for the function.
572-
ResolvedJavaMethod method = ((MethodPointer) info.getTargetObject()).getMethod();
576+
MethodPointer methodPointer = (MethodPointer) info.getTargetObject();
577+
ResolvedJavaMethod method = methodPointer.getMethod();
578+
HostedMethod target = (method instanceof HostedMethod) ? (HostedMethod) method : heap.getUniverse().lookup(method);
579+
if (!target.isCompiled()) {
580+
target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD);
581+
}
573582
// A reference to a method. Mark the relocation site using the symbol name.
574-
sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(method), false, 0L);
583+
sectionImpl.markRelocationSite(offset, RelocationKind.getDirect(functionPointerRelocationSize), localSymbolNameForMethod(target), false, 0L);
575584
}
576585

577586
private static boolean isAddendAligned(Architecture arch, long addend, RelocationKind kind) {
@@ -956,3 +965,12 @@ protected NativeTextSectionImpl(RelocatableBuffer relocatableBuffer, ObjectFile
956965
protected final NativeImageCodeCache codeCache;
957966
}
958967
}
968+
969+
@AutomaticFeature
970+
final class MethodPointerInvalidHandlerFeature implements Feature {
971+
@Override
972+
public void beforeAnalysis(BeforeAnalysisAccess a) {
973+
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
974+
access.registerAsCompiled(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD);
975+
}
976+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,11 @@
5555
import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo;
5656
import com.oracle.svm.hosted.meta.HostedClass;
5757
import com.oracle.svm.hosted.meta.HostedField;
58-
import com.oracle.svm.hosted.meta.HostedMethod;
5958
import com.oracle.svm.hosted.meta.MaterializedConstantFields;
6059
import com.oracle.svm.hosted.meta.MethodPointer;
6160

6261
import jdk.vm.ci.meta.JavaConstant;
6362
import jdk.vm.ci.meta.JavaKind;
64-
import jdk.vm.ci.meta.ResolvedJavaMethod;
6563
import sun.misc.Unsafe;
6664

6765
/**
@@ -242,14 +240,8 @@ private void addNonDataRelocation(RelocatableBuffer buffer, int index, Relocated
242240
mustBeReferenceAligned(index);
243241
assert pointer instanceof CFunctionPointer : "unknown relocated pointer " + pointer;
244242
assert pointer instanceof MethodPointer : "cannot create relocation for unknown FunctionPointer " + pointer;
245-
246-
ResolvedJavaMethod method = ((MethodPointer) pointer).getMethod();
247-
HostedMethod hMethod = method instanceof HostedMethod ? (HostedMethod) method : heap.getUniverse().lookup(method);
248-
if (hMethod.isCompiled()) {
249-
// Only compiled methods inserted in vtables require relocation.
250-
int pointerSize = ConfigurationValues.getTarget().wordSize;
251-
addDirectRelocationWithoutAddend(buffer, index, pointerSize, pointer);
252-
}
243+
int pointerSize = ConfigurationValues.getTarget().wordSize;
244+
addDirectRelocationWithoutAddend(buffer, index, pointerSize, pointer);
253245
}
254246

255247
private static void writePrimitive(RelocatableBuffer buffer, int index, JavaConstant con) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MethodPointer.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
import static com.oracle.svm.core.util.VMError.shouldNotReachHere;
2828

29+
import java.util.Objects;
30+
2931
import org.graalvm.nativeimage.c.function.CFunctionPointer;
3032
import org.graalvm.word.ComparableWord;
3133

@@ -34,20 +36,11 @@
3436
/**
3537
* A pointer to the compiled code of a method.
3638
*/
37-
public class MethodPointer implements CFunctionPointer {
38-
39+
public final class MethodPointer implements CFunctionPointer {
3940
private final ResolvedJavaMethod method;
4041

41-
public static CFunctionPointer factory(ResolvedJavaMethod method) {
42-
if (method == null) {
43-
return null;
44-
} else {
45-
return new MethodPointer(method);
46-
}
47-
}
48-
49-
protected MethodPointer(ResolvedJavaMethod method) {
50-
assert method != null;
42+
public MethodPointer(ResolvedJavaMethod method) {
43+
Objects.requireNonNull(method);
5144
this.method = method;
5245
}
5346

0 commit comments

Comments
 (0)