Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GR-49517] Add support for Windows x64 unwind info. #9062

Merged
merged 1 commit into from
Jul 22, 2024
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
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-54476): Issue a deprecation warning on first use of a legacy `graal.` prefix (see GR-49960 in [Compiler changelog](../compiler/CHANGELOG.md)).
The warning is planned to be replaced by an error in GraalVM for JDK 25.
* (GR-48384) Added a GDB Python script (`gdb-debughelpers.py`) to improve the Native Image debugging experience.
* (GR-49517) Add support for emitting Windows x64 unwind info. This enables stack walking in native tooling such as debuggers and profilers.

## GraalVM for JDK 23 (Internal Version 24.1.0)
* (GR-51520) The old class initialization strategy, which was deprecated in GraalVM for JDK 22, is removed. The option `StrictImageHeap` no longer has any effect.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@
import java.util.function.Consumer;
import java.util.stream.StreamSupport;

import jdk.graal.compiler.debug.DebugContext;

import com.oracle.objectfile.debuginfo.DebugInfoProvider;
import com.oracle.objectfile.elf.ELFObjectFile;
import com.oracle.objectfile.macho.MachOObjectFile;
import com.oracle.objectfile.pecoff.PECoffObjectFile;

import jdk.graal.compiler.debug.DebugContext;
import sun.nio.ch.DirectBuffer;

/**
Expand Down Expand Up @@ -254,6 +253,11 @@ public enum RelocationKind {
DIRECT_2,
DIRECT_4,
DIRECT_8,
/**
* The relocation's symbol provides an address whose image-base-relative value (plus addend)
* supplies the fixup bytes.
*/
ADDR32NB_4,
/**
* The index of the object file section containing the relocation's symbol supplies the
* fixup bytes. (used in CodeView debug information)
Expand Down Expand Up @@ -371,6 +375,7 @@ public static int getRelocationSize(RelocationKind kind) {
return 2;
case DIRECT_4:
case PC_RELATIVE_4:
case ADDR32NB_4:
case SECREL_4:
return 4;
case AARCH64_R_AARCH64_ADR_PREL_PG_HI21:
Expand Down Expand Up @@ -522,10 +527,13 @@ public interface NobitsSectionImpl extends ElementImpl {
// convenience overrides when specifying neither segment nor segment name

public Section newUserDefinedSection(String name, ElementImpl impl) {
final Segment segment = getOrCreateSegment(null, name, false, false);
final int alignment = getWordSizeInBytes();
final Section result = newUserDefinedSection(segment, name, alignment, impl);
return result;
return newUserDefinedSection(name, alignment, impl);
}

public Section newUserDefinedSection(String name, int alignment, ElementImpl impl) {
Segment segment = getOrCreateSegment(null, name, false, false);
return newUserDefinedSection(segment, name, alignment, impl);
}

public Section newDebugSection(String name, ElementImpl impl) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ enum IMAGE_RELOCATION {
* Relocation types
*/
static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0;
static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
static final int IMAGE_REL_AMD64_ADDR64 = 0x1;
static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
static final int IMAGE_REL_AMD64_ADDR32NB = 0x3;
static final int IMAGE_REL_AMD64_REL32 = 0x4;
static final int IMAGE_REL_AMD64_REL32_1 = 0x5;
static final int IMAGE_REL_AMD64_REL32_2 = 0x6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public static PECoffRelocationMethod getRelocation(PECoffMachine m, RelocationKi
return PECoffX86_64Relocation.ADDR32;
case PC_RELATIVE_4:
return PECoffX86_64Relocation.REL32;
case ADDR32NB_4:
return PECoffX86_64Relocation.ADDR32NB;
case SECTION_2:
return PECoffX86_64Relocation.SECTION;
case SECREL_4:
Expand Down Expand Up @@ -125,10 +127,16 @@ public long toLong() {
return IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR32;
}
},
SECREL {
ADDR32NB {
@Override
public long toLong() {
return IMAGE_RELOCATION.IMAGE_REL_AMD64_SECREL;
return IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR32NB;
}
},
REL32 {
@Override
public long toLong() {
return IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
}
},
SECTION {
Expand All @@ -137,10 +145,10 @@ public long toLong() {
return IMAGE_RELOCATION.IMAGE_REL_AMD64_SECTION;
}
},
REL32 {
SECREL {
@Override
public long toLong() {
return IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
return IMAGE_RELOCATION.IMAGE_REL_AMD64_SECREL;
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected Segment getOrCreateSegment(String maybeSegmentName, String sectionName

@Override
public PECoffUserDefinedSection newUserDefinedSection(Segment segment, String name, int alignment, ElementImpl impl) {
PECoffUserDefinedSection userDefined = new PECoffUserDefinedSection(this, name, alignment, impl);
PECoffUserDefinedSection userDefined = new PECoffUserDefinedSection(this, name, alignment, impl, EnumSet.of(PECoffSectionFlag.INITIALIZED_DATA, PECoffSectionFlag.READ));
assert userDefined.getImpl() == impl;
if (segment != null) {
getOrCreateSegment(segment.getName(), name, true, false).add(userDefined);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.ArrayList;

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId;

import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
import jdk.graal.compiler.core.common.cfg.BasicBlock;
Expand Down Expand Up @@ -86,14 +87,13 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA
*/
buffer.init(instructions);
if (block.isExceptionEntry()) {
buffer.append(lirGenRes.getFirstInsertPosition(), new SpillFramePointerOp(true));
buffer.append(lirGenRes.getFirstInsertPosition(), new ReloadFramePointerOp());
}
for (int i = 0; i < instructions.size(); i++) {
if (instructions.get(i) instanceof AMD64Call.CallOp callOp) {
buffer.append(i, new SpillFramePointerOp());
if (callOp.destroysCallerSavedRegisters()) {
buffer.append(i + 1, new ReloadFramePointerOp());
}
buffer.append(i + 1, new ReloadFramePointerOp(!callOp.destroysCallerSavedRegisters()));
}
}
buffer.finish();
Expand Down Expand Up @@ -121,29 +121,49 @@ private static boolean modifiesStackPointer(LIR lir) {
public static class SpillFramePointerOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<SpillFramePointerOp> TYPE = LIRInstructionClass.create(SpillFramePointerOp.class);

private final boolean recordMarkOnly;

SpillFramePointerOp() {
this(false);
}

SpillFramePointerOp(boolean recordMarkOnly) {
super(TYPE);
this.recordMarkOnly = recordMarkOnly;
}

@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
var frameMap = (SubstrateAMD64Backend.SubstrateAMD64FrameMap) crb.frameMap;
masm.movq(masm.makeAddress(AMD64.rsp, frameMap.getFramePointerSaveAreaOffset()), AMD64.rbp);
if (!recordMarkOnly) {
var frameMap = (SubstrateAMD64Backend.SubstrateAMD64FrameMap) crb.frameMap;
masm.movq(masm.makeAddress(AMD64.rsp, frameMap.getFramePointerSaveAreaOffset()), AMD64.rbp);
}
crb.recordMark(SubstrateMarkId.FRAME_POINTER_SPILLED);
}
}

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

private final boolean recordMarkOnly;

ReloadFramePointerOp() {
this(false);
}

ReloadFramePointerOp(boolean recordMarkOnly) {
super(TYPE);
this.recordMarkOnly = recordMarkOnly;
}

@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
var frameMap = (SubstrateAMD64Backend.SubstrateAMD64FrameMap) crb.frameMap;
masm.movq(AMD64.rbp, masm.makeAddress(AMD64.rsp, frameMap.getFramePointerSaveAreaOffset()));
if (!recordMarkOnly) {
var frameMap = (SubstrateAMD64Backend.SubstrateAMD64FrameMap) crb.frameMap;
masm.movq(AMD64.rbp, masm.makeAddress(AMD64.rsp, frameMap.getFramePointerSaveAreaOffset()));
}
crb.recordMark(SubstrateMarkId.FRAME_POINTER_RELOADED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_DECD_RSP;
import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_END;
import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_PUSH_RBP;
import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_SET_FRAME_POINTER;
import static com.oracle.svm.core.util.VMError.shouldNotReachHere;
import static com.oracle.svm.core.util.VMError.unsupportedFeature;
import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.REG;
Expand Down Expand Up @@ -62,6 +64,7 @@
import com.oracle.svm.core.graal.code.AssignedLocation;
import com.oracle.svm.core.graal.code.CGlobalDataInfo;
import com.oracle.svm.core.graal.code.PatchConsumerFactory;
import com.oracle.svm.core.graal.code.SharedCompilationResult;
import com.oracle.svm.core.graal.code.StubCallingConvention;
import com.oracle.svm.core.graal.code.SubstrateBackend;
import com.oracle.svm.core.graal.code.SubstrateCallingConvention;
Expand Down Expand Up @@ -1244,6 +1247,7 @@ protected void maybePushBasePointer(CompilationResultBuilder crb, AMD64MacroAsse
SubstrateAMD64FrameMap frameMap = (SubstrateAMD64FrameMap) crb.frameMap;
if (frameMap.preserveFramePointer() || isCalleeSaved(rbp, frameMap.getRegisterConfig(), method)) {
asm.push(rbp);
crb.recordMark(PROLOGUE_PUSH_RBP);
}
if (frameMap.preserveFramePointer() && !frameMap.needsFramePointer()) {
/* We won't be using rbp as a frame pointer, so we form a frame chain here. */
Expand Down Expand Up @@ -1272,6 +1276,7 @@ private static void maybeSetFramePointer(CompilationResultBuilder crb, AMD64Macr
/* Set the frame pointer to [rsp]. */
asm.movq(rbp, rsp);
}
crb.recordMark(PROLOGUE_SET_FRAME_POINTER);
}
}

Expand All @@ -1296,11 +1301,12 @@ public void leave(CompilationResultBuilder crb) {
} else {
asm.incrementq(rsp, frameMap.frameSize());
}
crb.recordMark(SubstrateMarkId.EPILOGUE_INCD_RSP);

if (frameMap.preserveFramePointer() || isCalleeSaved(rbp, frameMap.getRegisterConfig(), method)) {
asm.pop(rbp);
crb.recordMark(SubstrateMarkId.EPILOGUE_POP_RBP);
}

crb.recordMark(SubstrateMarkId.EPILOGUE_INCD_RSP);
}

@Override
Expand Down Expand Up @@ -1748,10 +1754,15 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult
FrameContext frameContext = createFrameContext(method, stubType, callingConvention);
DebugContext debug = lir.getDebug();
Register uncompressedNullRegister = useLinearPointerCompression() ? ReservedRegisters.singleton().getHeapBaseRegister() : Register.None;
CompilationResultBuilder tasm = factory.createBuilder(getProviders(), lirGenResult.getFrameMap(), masm, dataBuilder, frameContext, options, debug, compilationResult,
uncompressedNullRegister, lir);
tasm.setTotalFrameSize(lirGenResult.getFrameMap().totalFrameSize());
return tasm;
CompilationResultBuilder crb = factory.createBuilder(getProviders(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, uncompressedNullRegister, lir);
crb.setTotalFrameSize(frameMap.totalFrameSize());
var sharedCompilationResult = (SharedCompilationResult) compilationResult;
var substrateAMD64FrameMap = (SubstrateAMD64FrameMap) frameMap;
sharedCompilationResult.setFrameSize(substrateAMD64FrameMap.frameSize());
if (substrateAMD64FrameMap.needsFramePointer()) {
sharedCompilationResult.setFramePointerSaveAreaOffset(substrateAMD64FrameMap.getFramePointerSaveAreaOffset());
}
return crb;
}

protected AMD64MacroAssembler createAssembler(OptionValues options) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024, 2024, 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 com.oracle.svm.core.graal.code;

import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.common.CompilationIdentifier;

/** Base class common to both hosted and runtime compilations. */
public abstract class SharedCompilationResult extends CompilationResult {
private int frameSize = -1;
private int framePointerSaveAreaOffset = -1;

public SharedCompilationResult(CompilationIdentifier compilationId, String name) {
super(compilationId, name);
}

public int getFrameSize() {
assert frameSize != -1 : "frame size not set";
return frameSize;
}

public void setFrameSize(int frameSize) {
this.frameSize = frameSize;
}

public int getFramePointerSaveAreaOffset() {
return framePointerSaveAreaOffset;
}

public void setFramePointerSaveAreaOffset(int framePointerSaveAreaOffset) {
this.framePointerSaveAreaOffset = framePointerSaveAreaOffset;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@

import java.lang.reflect.Method;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.LocationIdentity;

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode;
import com.oracle.svm.core.graal.snippets.CFunctionSnippets;
import com.oracle.svm.core.meta.SharedMethod;
import com.oracle.svm.core.nodes.CFunctionPrologueDataNode;
import com.oracle.svm.core.thread.VMThreads.StatusSupport;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.common.CompilationIdentifier;
import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig;
Expand All @@ -43,19 +56,6 @@
import jdk.graal.compiler.phases.BasePhase;
import jdk.graal.compiler.phases.tiers.SuitesProvider;
import jdk.graal.compiler.phases.util.Providers;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.LocationIdentity;

import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.graal.meta.RuntimeConfiguration;
import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode;
import com.oracle.svm.core.graal.snippets.CFunctionSnippets;
import com.oracle.svm.core.meta.SharedMethod;
import com.oracle.svm.core.nodes.CFunctionPrologueDataNode;
import com.oracle.svm.core.thread.VMThreads.StatusSupport;
import com.oracle.svm.core.util.VMError;

import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.RegisterValue;
Expand All @@ -70,11 +70,16 @@ public enum SubstrateMarkId implements CompilationResult.MarkId {
* instructions in the compilation.
*/
PROLOGUE_START(true),
PROLOGUE_PUSH_RBP(true),
PROLOGUE_DECD_RSP(true),
PROLOGUE_SET_FRAME_POINTER(true),
PROLOGUE_SAVED_REGS(true),
PROLOGUE_END(true),
FRAME_POINTER_SPILLED(true),
FRAME_POINTER_RELOADED(true),
EPILOGUE_START(false),
EPILOGUE_INCD_RSP(true),
EPILOGUE_POP_RBP(true),
EPILOGUE_END(true);

final boolean isMarkAfter;
Expand Down Expand Up @@ -149,7 +154,7 @@ public SuitesProvider getSuites() {
}

public CompilationResult newCompilationResult(CompilationIdentifier compilationIdentifier, String name) {
return new CompilationResult(compilationIdentifier, name) {
return new SharedCompilationResult(compilationIdentifier, name) {
@Override
public void close(OptionValues options) {
/*
Expand Down
Loading
Loading