Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions docs/reference-manual/native-image/DebugInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,3 +648,21 @@ end
(gdb) hubname_indirect 0x1dc860
0x7ffff78a52f0: "java.lang.Class"
```

## Debug Helper Methods

On platforms where the debugging information is not fully supported, or when debugging complex issues, it can be helpful to print or query high-level information about the Native Image execution state.
For those scenarios, Native Image provides debug helper methods that can be embedded into a native image by specifying the build-time option `-H:+IncludeDebugHelperMethods`.
While debugging, it is then possible to invoke those debug helper methods like any normal C method.
This functionality is compatible with pretty much any debugger.

While debugging with gdb, the following command can be used to list all debug helper methods that are embedded into the native image:
```
(gdb) info functions svm_dbg_
```

Before invoking a method, it is best to directly look at the source code of the Java class `DebugHelper` to determine which arguments each method expects.
For example, calling the method below prints high-level information about the Native Image execution state similar to what is printed for a fatal error:
```
(gdb) call svm_dbg_print_fatalErrorDiagnostics($r15, $rsp, $rip)
```
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
import com.oracle.svm.core.heap.ReferenceHandlerThread;
import com.oracle.svm.core.heap.ReferenceInternals;
import com.oracle.svm.core.heap.RuntimeCodeInfoGCSupport;
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference;
import com.oracle.svm.core.locks.VMCondition;
import com.oracle.svm.core.locks.VMMutex;
Expand Down Expand Up @@ -643,9 +642,8 @@ public boolean printLocationInfo(Log log, UnsignedWord value, boolean allowJavaH
Pointer ptr = (Pointer) value;
if (printLocationInfo(log, ptr, allowJavaHeapAccess, allowUnsafeOperations)) {
if (allowJavaHeapAccess && objectHeaderImpl.pointsToObjectHeader(ptr)) {
DynamicHub hub = objectHeaderImpl.readDynamicHubFromPointer(ptr);
log.indent(true);
log.string("hub=").string(hub.getName());
SubstrateDiagnostics.printObjectInfo(log, ptr);
log.redent(false);
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,14 @@ public DynamicHub dynamicHubFromObjectHeader(UnsignedWord header) {
return (DynamicHub) objectValue;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
@Override
public Pointer readPotentialDynamicHubFromPointer(Pointer ptr) {
UnsignedWord potentialHeader = ObjectHeaderImpl.readHeaderFromPointer(ptr);
UnsignedWord pointerBits = clearBits(potentialHeader);
if (ReferenceAccess.singleton().haveCompressedReferences()) {
UnsignedWord compressedBits = pointerBits.unsignedShiftRight(getCompressionShift());
return KnownIntrinsics.heapBase().add(compressedBits.shiftLeft(getCompressionShift()));
UnsignedWord compressedBits = pointerBits.unsignedShiftRight(ObjectHeader.getCompressionShift());
return KnownIntrinsics.heapBase().add(compressedBits.shiftLeft(ObjectHeader.getCompressionShift()));
} else {
return (Pointer) pointerBits;
}
Expand Down Expand Up @@ -378,9 +379,4 @@ static int getReferenceSize() {
static boolean hasBase() {
return ImageSingletons.lookup(CompressEncoding.class).hasBase();
}

@Fold
static int getCompressionShift() {
return ReferenceAccess.singleton().getCompressEncoding().getShift();
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import com.oracle.svm.core.deopt.DeoptimizedFrame;
import com.oracle.svm.core.deopt.Deoptimizer;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicWord;
import com.oracle.svm.core.locks.VMLockSupport;
import com.oracle.svm.core.log.Log;
Expand Down Expand Up @@ -133,6 +134,19 @@ public static void printLocationInfo(Log log, UnsignedWord value, boolean allowJ
}
}

@Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false)
public static void printObjectInfo(Log log, Pointer ptr) {
DynamicHub objHub = Heap.getHeap().getObjectHeader().readDynamicHubFromPointer(ptr);
if (objHub == DynamicHub.fromClass(DynamicHub.class)) {
// The pointer is already a hub, so print some information about the hub.
DynamicHub hub = (DynamicHub) ptr.toObject();
log.string("is the hub of ").string(hub.getName());
} else {
// The pointer is an object, so print some information about the object's hub.
log.string("is an object of type ").string(objHub.getName());
}
}

/**
* See {@link #printInformation(Log, Pointer, CodePointer, RegisterDumper.Context, boolean)}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ public static int codeAlignment() {
@Option(help = "Determines if VM internal threads (e.g., a dedicated VM operation or reference handling thread) are allowed in this image.", type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> AllowVMInternalThreads = new HostedOptionKey<>(true);

@Option(help = "Determines if debugging-specific helper methods are embedded into the image. Those methods can be called directly from the debugger to obtain or print additional information.", type = OptionType.Debug) //
public static final HostedOptionKey<Boolean> IncludeDebugHelperMethods = new HostedOptionKey<>(false);

@APIOption(name = "-g", fixedValue = "2", customHelp = "generate debugging information")//
@Option(help = "Insert debug info into the generated native image or library")//
public static final HostedOptionKey<Integer> GenerateDebugInfo = new HostedOptionKey<>(0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.svm.core.heap;

import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.word.Word;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand Down Expand Up @@ -70,11 +71,13 @@ public static DynamicHub readDynamicHubFromObject(Object o) {
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public abstract DynamicHub readDynamicHubFromPointer(Pointer ptr);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public abstract Pointer readPotentialDynamicHubFromPointer(Pointer ptr);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public abstract void initializeHeaderOfNewObject(Pointer objectPointer, Word objectHeader);

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean pointsToObjectHeader(Pointer ptr) {
Pointer potentialDynamicHub = readPotentialDynamicHubFromPointer(ptr);
if (Heap.getHeap().isInImageHeap(potentialDynamicHub)) {
Expand All @@ -84,4 +87,8 @@ public boolean pointsToObjectHeader(Pointer ptr) {
return false;
}

@Fold
protected static int getCompressionShift() {
return ReferenceAccess.singleton().getCompressEncoding().getShift();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,17 @@ public String getName() {
return name;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean isInstanceClass() {
return HubType.isInstance(hubType);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean isStoredContinuationClass() {
return HubType.isStoredContinuation(hubType);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean isReferenceInstanceClass() {
return HubType.isReferenceInstance(hubType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.oracle.svm.core.hub;

import com.oracle.svm.core.annotate.DuplicatedInNativeCode;
import com.oracle.svm.core.annotate.Uninterruptible;

@DuplicatedInNativeCode
public enum HubType {
Expand All @@ -44,22 +45,27 @@ public enum HubType {
this.value = value;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getValue() {
return value;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isInstance(int hubType) {
return hubType <= StoredContinuation.getValue();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isReferenceInstance(int hubType) {
return hubType == InstanceReference.getValue();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isStoredContinuation(int hubType) {
return hubType == StoredContinuation.getValue();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isArray(int hubType) {
return hubType >= TypeArray.getValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public static boolean isAbstract(int encoding) {
return encoding == ABSTRACT_VALUE;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isInstance(int encoding) {
return encoding > LAST_SPECIAL_VALUE;
}
Expand Down