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-38416] Implement debug location info #4505

Merged
merged 22 commits into from
May 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d88c987
Reimplement inline method and line debug info generation using Compil…
adinn Jan 26, 2022
6456883
Update expected debuginfotest output.
adinn Jan 31, 2022
2070ace
Correct the algorithm that walks the compiler result frame tree.
adinn Feb 11, 2022
76b2e98
Refactor DebugMethodInfo implementation classes to remove duplicated …
adinn Feb 23, 2022
f22d3cb
Refactor DebugInfo presentation of of param and local variables.
adinn Mar 1, 2022
cb2e3b5
First cut of local var info for stack and reg slots.
adinn Apr 6, 2022
93867a3
Add synthetic debug location info at start of compiled Java method.
adinn Apr 19, 2022
0448a5d
Fix problem when AnalysisMethod instances are found in frames.
adinn Apr 22, 2022
197b2ea
Allow for args being optimized out at start of inlined method.
adinn Apr 22, 2022
fb5d88b
Support primitive and null constant locals/params and correct stack l…
adinn Apr 26, 2022
83631af
Review rework update test of argument passing.
adinn May 3, 2022
4b28054
Review rework complete writing of locations to include object constants.
adinn May 3, 2022
8d75553
Extend debuginfo test to check inline constants
adinn May 4, 2022
bb29da1
Use OS-CPU specific calling convention for initial param reg mapping
adinn May 6, 2022
bb567ca
Document mappings from compiler register numbers to DWARF encodings.
adinn May 6, 2022
15e2046
Simplify Graal to DWARF register number mapping.
adinn May 9, 2022
d57108d
Correct typo in architecture name.
adinn May 9, 2022
2132bff
Handle bad source positions generated occasionally on AArch64.
adinn May 12, 2022
017a209
Fix problems found by Oracle gate checks.
adinn May 13, 2022
1c651c8
Fix problems with debug info test script due to variation in inlining.
adinn May 13, 2022
9dba331
Correct further output format issues with the debuginfotest script
adinn May 13, 2022
d47313e
Use equals test for method comparisons.
adinn May 13, 2022
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
4 changes: 2 additions & 2 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,12 +838,12 @@ def build_debug_test(extra_args):

build_debug_test(['-H:+SpawnIsolates'])
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest.isolates' : 'yes'})
os.environ.update({'debuginfotest_isolates' : 'yes'})
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=True"', '-x', join(parent, 'mx.substratevm/testhello.py'), join(path, 'hello.hello')])

build_debug_test(['-H:-SpawnIsolates'])
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest.isolates' : 'no'})
os.environ.update({'debuginfotest_isolates' : 'no'})
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=False"', '-x', join(parent, 'mx.substratevm/testhello.py'), join(path, 'hello.hello')])

def _javac_image(native_image, path, args=None):
Expand Down
3 changes: 3 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,9 @@
"jdk.internal.ref",
"sun.nio.ch",
],
"jdk.internal.vm.ci" : [
"jdk.vm.ci.code",
],
},
"checkstyle" : "com.oracle.svm.hosted",
"javaCompliance": "11+",
Expand Down
344 changes: 238 additions & 106 deletions substratevm/mx.substratevm/testhello.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFieldInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFrameSizeChange;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugInstanceTypeInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugMethodInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugRangeInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo;
Expand Down Expand Up @@ -285,32 +286,23 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa
String methodName = debugMethodInfo.name();
String resultTypeName = TypeEntry.canonicalize(debugMethodInfo.valueType());
int modifiers = debugMethodInfo.modifiers();
List<String> paramTypes = debugMethodInfo.paramTypes();
List<String> paramNames = debugMethodInfo.paramNames();
assert paramTypes.size() == paramNames.size();
int paramCount = paramTypes.size();
DebugLocalInfo[] paramInfos = debugMethodInfo.getParamInfo();
DebugLocalInfo thisParam = debugMethodInfo.getThisParamInfo();
int paramCount = paramInfos.length;
debugContext.log("typename %s adding %s method %s %s(%s)\n",
typeName, memberModifiers(modifiers), resultTypeName, methodName, formatParams(paramTypes, paramNames));
typeName, memberModifiers(modifiers), resultTypeName, methodName, formatParams(paramInfos));
TypeEntry resultType = debugInfoBase.lookupTypeEntry(resultTypeName);
TypeEntry[] paramTypeArray = null;
String[] paramNameArray = null;
if (paramCount != 0) {
paramTypeArray = new TypeEntry[paramCount];
paramNameArray = new String[paramCount];
int idx = 0;
for (String paramTypeName : paramTypes) {
TypeEntry paramType = debugInfoBase.lookupTypeEntry(TypeEntry.canonicalize(paramTypeName));
paramTypeArray[idx++] = paramType;
}
paramNameArray = paramNames.toArray(paramNameArray);
TypeEntry[] typeEntries = new TypeEntry[paramCount];
for (int i = 0; i < paramCount; i++) {
typeEntries[i] = debugInfoBase.lookupTypeEntry(TypeEntry.canonicalize(paramInfos[i].typeName()));
}
/*
* n.b. the method file may differ from the owning class file when the method is a
* substitution
*/
FileEntry methodFileEntry = debugInfoBase.ensureFileEntry(debugMethodInfo);
MethodEntry methodEntry = new MethodEntry(debugInfoBase, debugMethodInfo, methodFileEntry, methodName,
this, resultType, paramTypeArray, paramNameArray);
this, resultType, typeEntries, paramInfos, thisParam);
indexMethodEntry(methodEntry);

return methodEntry;
Expand All @@ -326,21 +318,18 @@ protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debug
return fieldEntry;
}

private static String formatParams(List<String> paramTypes, List<String> paramNames) {
if (paramNames.size() == 0) {
private static String formatParams(DebugLocalInfo[] paramInfo) {
if (paramInfo.length == 0) {
return "";
}
StringBuilder builder = new StringBuilder();
String separator = "";
for (int i = 0; i < paramNames.size(); i++) {
builder.append(separator);
builder.append(paramTypes.get(i));
String paramName = paramNames.get(i);
if (paramName.length() > 0) {
builder.append(' ');
builder.append(paramName);
for (int i = 0; i < paramInfo.length; i++) {
if (i > 0) {
builder.append(", ");
}
separator = ", ";
builder.append(paramInfo[i].typeName());
builder.append(' ');
builder.append(paramInfo[i].name());
}

return builder.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.graalvm.compiler.debug.DebugContext;

import com.oracle.objectfile.debuginfo.DebugInfoProvider;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocationInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalValueInfo;
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo.DebugTypeKind;
import com.oracle.objectfile.elf.dwarf.DwarfDebugInfo;

Expand Down Expand Up @@ -255,8 +257,8 @@ public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
* Record all subranges even if they have no line or file so we at least get a symbol
* for them and don't see a break in the address range.
*/
debugCodeInfo.lineInfoProvider().forEach(debugLineInfo -> recursivelyAddSubRanges(debugLineInfo, primaryRange, classEntry, debugContext));
primaryRange.mergeSubranges(debugContext);
HashMap<DebugLocationInfo, Range> subRangeIndex = new HashMap<>();
debugCodeInfo.locationInfoProvider().forEach(debugLocationInfo -> addSubrange(debugLocationInfo, primaryRange, classEntry, subRangeIndex, debugContext));
}));

debugInfoProvider.dataInfoProvider().forEach(debugDataInfo -> debugDataInfo.debugContext((debugContext) -> {
Expand Down Expand Up @@ -338,45 +340,55 @@ ClassEntry lookupClassEntry(String typeName) {
}

/**
* Recursively creates subranges based on DebugLineInfo including, and appropriately linking,
* nested inline subranges.
* Recursively creates subranges based on DebugLocationInfo including, and appropriately
* linking, nested inline subranges.
*
* @param lineInfo
* @param locationInfo
* @param primaryRange
* @param classEntry
* @param debugContext
* @return the subrange for {@code lineInfo} linked with all its caller subranges up to the
* @return the subrange for {@code locationInfo} linked with all its caller subranges up to the
* primaryRange
*/
@SuppressWarnings("try")
private Range recursivelyAddSubRanges(DebugInfoProvider.DebugLineInfo lineInfo, Range primaryRange, ClassEntry classEntry, DebugContext debugContext) {
if (lineInfo == null) {
return primaryRange;
}
private Range addSubrange(DebugLocationInfo locationInfo, Range primaryRange, ClassEntry classEntry, HashMap<DebugLocationInfo, Range> subRangeIndex, DebugContext debugContext) {
/*
* We still insert subranges for the primary method but they don't actually count as inline.
* we only need a range so that subranges for inline code can refer to the top level line
* number
* number.
*/
boolean isInline = lineInfo.getCaller() != null;
assert (isInline || (lineInfo.name().equals(primaryRange.getMethodName()) && TypeEntry.canonicalize(lineInfo.ownerType().toJavaName()).equals(primaryRange.getClassName())));

Range caller = recursivelyAddSubRanges(lineInfo.getCaller(), primaryRange, classEntry, debugContext);
final String fileName = lineInfo.fileName();
final Path filePath = lineInfo.filePath();
final ResolvedJavaType ownerType = lineInfo.ownerType();
final String methodName = lineInfo.name();
final int lo = primaryRange.getLo() + lineInfo.addressLo();
final int hi = primaryRange.getLo() + lineInfo.addressHi();
final int line = lineInfo.line();
DebugLocationInfo callerLocationInfo = locationInfo.getCaller();
boolean isTopLevel = callerLocationInfo == null;
assert (!isTopLevel || (locationInfo.name().equals(primaryRange.getMethodName()) &&
TypeEntry.canonicalize(locationInfo.ownerType().toJavaName()).equals(primaryRange.getClassName())));
Range caller = (isTopLevel ? primaryRange : subRangeIndex.get(callerLocationInfo));
// the frame tree is walked topdown so inline ranges should always have a caller range
assert caller != null;

final String fileName = locationInfo.fileName();
final Path filePath = locationInfo.filePath();
final String fullPath = (filePath == null ? "" : filePath.toString() + "/") + fileName;
final ResolvedJavaType ownerType = locationInfo.ownerType();
final String methodName = locationInfo.name();
final int loOff = locationInfo.addressLo();
final int hiOff = locationInfo.addressHi() - 1;
final int lo = primaryRange.getLo() + locationInfo.addressLo();
final int hi = primaryRange.getLo() + locationInfo.addressHi();
final int line = locationInfo.line();
ClassEntry subRangeClassEntry = ensureClassEntry(ownerType);
MethodEntry subRangeMethodEntry = subRangeClassEntry.ensureMethodEntryForDebugRangeInfo(lineInfo, this, debugContext);
Range subRange = new Range(stringTable, subRangeMethodEntry, lo, hi, line, primaryRange, isInline, caller);
MethodEntry subRangeMethodEntry = subRangeClassEntry.ensureMethodEntryForDebugRangeInfo(locationInfo, this, debugContext);
Range subRange = new Range(stringTable, subRangeMethodEntry, lo, hi, line, primaryRange, isTopLevel, caller);
classEntry.indexSubRange(subRange);
try (DebugContext.Scope s = debugContext.scope("Subranges")) {
debugContext.log(DebugContext.DETAILED_LEVEL, "SubRange %s.%s %s %s:%d 0x%x, 0x%x]",
ownerType.toJavaName(), methodName, filePath, fileName, line, lo, hi);
subRangeIndex.put(locationInfo, subRange);
debugContext.log(DebugContext.DETAILED_LEVEL, "SubRange %s.%s %d %s:%d [0x%x, 0x%x] (%d, %d)",
ownerType.toJavaName(), methodName, subRange.getDepth(), fullPath, line, lo, hi, loOff, hiOff);
assert (callerLocationInfo == null || (callerLocationInfo.addressLo() <= loOff && callerLocationInfo.addressHi() >= hiOff)) : "parent range should enclose subrange!";
DebugLocalValueInfo[] localValueInfos = locationInfo.getLocalValueInfo();
for (int i = 0; i < localValueInfos.length; i++) {
DebugLocalValueInfo localValueInfo = localValueInfos[i];
debugContext.log(DebugContext.DETAILED_LEVEL, " locals[%d] %s:%s = %s", localValueInfo.slot(), localValueInfo.name(), localValueInfo.typeName(), localValueInfo);
}
subRange.setLocalValueInfo(localValueInfos);
return subRange;
}

Expand Down
Loading