Skip to content

[GR-34179] Upgrade CE debug info feature to provide information about Java types for Windows/PECOFF. #5621

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

Merged
merged 3 commits into from
Dec 16, 2022
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 @@ -10,6 +10,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-41100) Add support for `-XX:HeapDumpPath` to control where heap dumps are created.
* (GR-42148) Adjust build output to report types (primitives, classes, interfaces, and arrays) instead of classes and revise the output schema of `-H:BuildOutputJSONFile`.
* (GR-42375) Add `-H:±GenerateBuildArtifactsFile` option, which generates a `build-artifacts.json` file with a list of all artifacts produced by Native Image. `.build_artifacts.txt` files are now deprecated, disabled (can be re-enabled with env setting `NATIVE_IMAGE_DEPRECATED_BUILD_ARTIFACTS_TXT=true`), and will be removed in a future release.
* (GR-34179) Improved debugging support on Windows: Debug information now includes information about Java types (contributed by Red Hat).

## Version 22.3.0
* (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public String getFileName() {
}

@SuppressWarnings("unused")
String getFullFileName() {
public String getFullFileName() {
if (fileEntry != null) {
return fileEntry.getFullName();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@ public abstract class CVConstants {

/* CodeView section header signature */
static final int CV_SIGNATURE_C13 = 4;

static final int CV_AMD64_R8 = 336;
static final int CV_AMD64_R9 = 337;
static final int CV_AMD64_R10 = 338;
static final int CV_AMD64_R11 = 339;
static final int CV_AMD64_R12 = 340;
static final int CV_AMD64_R13 = 341;
static final int CV_AMD64_R14 = 342;
static final int CV_AMD64_R15 = 343;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ public abstract class CVDebugConstants {

/* Subcommands in DEBUG_S_SYMBOLS section. */
static final short S_END = 0x0006;
static final short S_OBJNAME = 0x1101;
static final short S_FRAMEPROC = 0x1012;
static final short S_GPROC32 = 0x1110;
static final short S_OBJNAME = 0x1101;
static final short S_UDT = 0x1108;
static final short S_LDATA32 = 0x110c; /* Local static. */
static final short S_GDATA32 = 0x110d; /* Global static. */
static final short S_GPROC32 = 0x1110; /* Global procedure. */
static final short S_REGREL32 = 0x1111;
static final short S_COMPILE3 = 0x113c;
static final short S_ENVBLOCK = 0x113d;
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,23 @@ public final class CVDebugInfo extends DebugInfoBase {
private final CVTypeSectionImpl cvTypeSection;
private DebugContext debugContext;

/* Register constants for Windows x86_64 */
/* See AMD64ReservedRegisters.java. */
public static final byte RHEAPBASE_X86 = (byte) 14;
public static final byte RTHREAD_X86 = (byte) 15;

private final byte heapbaseRegister;
private final byte threadRegister;

public CVDebugInfo(PECoffMachine machine, ByteOrder byteOrder) {
super(byteOrder);
cvSymbolSection = new CVSymbolSectionImpl(this);
cvTypeSection = new CVTypeSectionImpl(this);
if (machine != PECoffMachine.X86_64) {
/* room for future aarch64 port */
if (machine == PECoffMachine.X86_64) {
this.heapbaseRegister = RHEAPBASE_X86;
this.threadRegister = RTHREAD_X86;
} else {
/* room for future aach64 port */
throw GraalError.shouldNotReachHere("Unsupported architecture on Windows");
}
}
Expand All @@ -61,6 +72,15 @@ public CVTypeSectionImpl getCVTypeSection() {
return cvTypeSection;
}

public byte getHeapbaseRegister() {
return heapbaseRegister;
}

@SuppressWarnings("unused")
public byte getThreadRegister() {
return threadRegister;
}

public DebugContext getDebugContext() {
return debugContext;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2020, Red Hat Inc. 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.objectfile.pecoff.cv;

import com.oracle.objectfile.debugentry.FieldEntry;
import com.oracle.objectfile.debugentry.MethodEntry;
import com.oracle.objectfile.debugentry.TypeEntry;

final class CVNames {

static String typeNameToCodeViewName(String typeName) {
return typeName.replace('.', '_').replace("[]", "_array");
}

static String typeNameToCodeViewName(TypeEntry typeEntry) {
return typeNameToCodeViewName(typeEntry.getTypeName());
}

static String methodNameToCodeViewName(MethodEntry memberEntry) {
return typeNameToCodeViewName(memberEntry.ownerType()) + "::" + memberEntry.methodName();
}

static String fieldNameToCodeViewName(FieldEntry memberEntry) {
return typeNameToCodeViewName(memberEntry.ownerType()) + "::" + memberEntry.fieldName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,92 @@ public String toString() {
}
}

private abstract static class CVSymbolData32Record extends CVSymbolSubrecord {

protected final int typeIndex;
protected final int offset;
protected final short segment;
protected final String displayName;
protected final String symbolName;

protected CVSymbolData32Record(CVDebugInfo cvDebugInfo, short cmd, String symbolName, String displayName, int typeIndex, int offset, short segment) {
super(cvDebugInfo, cmd);
assert symbolName != null;
this.displayName = displayName;
this.symbolName = symbolName;
this.typeIndex = typeIndex;
this.offset = offset;
this.segment = segment;
}

@Override
protected int computeContents(byte[] buffer, int initialPos) {
int pos = CVUtil.putInt(typeIndex, buffer, initialPos);
pos = cvDebugInfo.getCVSymbolSection().markRelocationSite(buffer, pos, symbolName, offset);
pos = CVUtil.putUTF8StringBytes(displayName, buffer, pos);
return pos;
}
}

public static class CVSymbolGData32Record extends CVSymbolData32Record {

CVSymbolGData32Record(CVDebugInfo cvDebugInfo, String symbolName, String displayName, int typeIndex, int offset, short segment) {
super(cvDebugInfo, CVDebugConstants.S_GDATA32, symbolName, displayName, typeIndex, offset, segment);
}

@Override
public String toString() {
return String.format("S_GDATA32 name=%s(%s) offset=0x%x type=0x%x", symbolName, displayName, offset, typeIndex);
}
}

@SuppressWarnings("unused")
public static class CVSymbolLData32Record extends CVSymbolData32Record {

CVSymbolLData32Record(CVDebugInfo cvDebugInfo, String symbolName, String displayName, int typeIndex, int offset, short segment) {
super(cvDebugInfo, CVDebugConstants.S_LDATA32, symbolName, displayName, typeIndex, offset, segment);
}

CVSymbolLData32Record(CVDebugInfo cvDebugInfo, String symbolName, int typeIndex, int offset, short segment) {
super(cvDebugInfo, CVDebugConstants.S_LDATA32, symbolName, symbolName, typeIndex, offset, segment);
}

@Override
public String toString() {
return String.format("S_LDATA32 name=%s(%s) offset=0x%x type=0x%x", symbolName, displayName, offset, typeIndex);
}
}

public static class CVSymbolRegRel32Record extends CVSymbolSubrecord {

private final String name;
private final int typeIndex;
private final int offset;
private final short register;

CVSymbolRegRel32Record(CVDebugInfo debugInfo, String name, int typeIndex, int offset, short register) {
super(debugInfo, CVDebugConstants.S_REGREL32);
this.name = name;
this.typeIndex = typeIndex;
this.offset = offset;
this.register = register;
}

@Override
protected int computeContents(byte[] buffer, int initialPos) {
int pos = CVUtil.putInt(offset, buffer, initialPos);
pos = CVUtil.putInt(typeIndex, buffer, pos);
pos = CVUtil.putShort(register, buffer, pos);
pos = CVUtil.putUTF8StringBytes(name, buffer, pos);
return pos;
}

@Override
public String toString() {
return String.format("S_REGREL32 name=%s offset=(r%d + 0x%x) type=0x%x)", name, register, offset, typeIndex);
}
}

/*
* Creating a proc32 record has a side effect: two relocation entries are added to the section
* relocation table; they refer back to the global symbol.
Expand All @@ -258,15 +344,14 @@ public static class CVSymbolGProc32Record extends CVSymbolSubrecord {
private final int debugStart;
private final int debugEnd;
private final int typeIndex;
private final int offset;
private final short segment;
private final byte flags;
private final String symbolName;
private final String displayName;

CVSymbolGProc32Record(CVDebugInfo cvDebugInfo, short cmd, String symbolName, String displayName, int pparent, int pend, int pnext, int proclen, int debugStart, int debugEnd, int typeIndex,
int offset, short segment, byte flags) {
super(cvDebugInfo, cmd);
CVSymbolGProc32Record(CVDebugInfo cvDebugInfo, String symbolName, String displayName, int pparent, int pend, int pnext, int proclen, int debugStart, int debugEnd, int typeIndex,
short segment, byte flags) {
super(cvDebugInfo, CVDebugConstants.S_GPROC32);
this.symbolName = symbolName;
this.displayName = displayName;
this.pparent = pparent;
Expand All @@ -276,16 +361,10 @@ public static class CVSymbolGProc32Record extends CVSymbolSubrecord {
this.debugStart = debugStart;
this.debugEnd = debugEnd;
this.typeIndex = typeIndex;
this.offset = offset;
this.segment = segment;
this.flags = flags;
}

CVSymbolGProc32Record(CVDebugInfo cvDebugInfo, String symbolName, String displayName, int pparent, int pend, int pnext, int proclen, int debugStart, int debugEnd, int typeIndex, int offset,
short segment, byte flags) {
this(cvDebugInfo, CVDebugConstants.S_GPROC32, symbolName, displayName, pparent, pend, pnext, proclen, debugStart, debugEnd, typeIndex, offset, segment, flags);
}

@Override
protected int computeContents(byte[] buffer, int initialPos) {
int pos = CVUtil.putInt(pparent, buffer, initialPos);
Expand All @@ -303,8 +382,8 @@ protected int computeContents(byte[] buffer, int initialPos) {

@Override
public String toString() {
return String.format("S_GPROC32 name=%s/%s parent=%d debugstart=0x%x debugend=0x%x len=0x%x seg:offset=0x%x:0x%x type=0x%x flags=0x%x)", displayName, symbolName, pparent, debugStart,
debugEnd, proclen, segment, offset, typeIndex, flags);
return String.format("S_GPROC32 name=%s/%s parent=%d debugstart=0x%x debugend=0x%x len=0x%x seg:offset=0x%x:0 type=0x%x flags=0x%x)", displayName, symbolName, pparent, debugStart,
debugEnd, proclen, segment, typeIndex, flags);
}
}

Expand Down Expand Up @@ -351,6 +430,30 @@ public String toString() {
}
}

public static final class CVSymbolUDTRecord extends CVSymbolSubrecord {

private final int typeIdx;
private final String typeName;

CVSymbolUDTRecord(CVDebugInfo cvDebugInfo, int typeIdx, String typeName) {
super(cvDebugInfo, CVDebugConstants.S_UDT);
this.typeIdx = typeIdx;
this.typeName = typeName;
}

@Override
protected int computeContents(byte[] buffer, int initialPos) {
int pos = CVUtil.putInt(typeIdx, buffer, initialPos);
pos = CVUtil.putUTF8StringBytes(typeName, buffer, pos);
return pos;
}

@Override
public String toString() {
return String.format("S_UDT type=0x%x typename=%s", typeIdx, typeName);
}
}

public static class CVSymbolEndRecord extends CVSymbolSubrecord {

CVSymbolEndRecord(CVDebugInfo cvDebugInfo, short cmd) {
Expand Down
Loading