Skip to content

Commit da18562

Browse files
[GR-62990] Fields containing classes are not properly supported by the debug info.
PullRequest: graal/20333
2 parents 0f6f3d7 + 01934cb commit da18562

File tree

15 files changed

+424
-193
lines changed

15 files changed

+424
-193
lines changed

substratevm/debug/gdbpy/gdb-debughelpers.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class SVMUtil:
108108
string_type = gdb.lookup_type("java.lang.String")
109109
enum_type = gdb.lookup_type("java.lang.Enum")
110110
object_type = gdb.lookup_type("java.lang.Object")
111-
hub_type = gdb.lookup_type("java.lang.Class")
111+
hub_type = gdb.lookup_type("Encoded$Dynamic$Hub")
112112
null = gdb.Value(0).cast(object_type.pointer())
113113
classloader_type = gdb.lookup_type("java.lang.ClassLoader")
114114
wrapper_types = [gdb.lookup_type(f'java.lang.{x}') for x in
@@ -141,7 +141,7 @@ def get_uncompressed_type(cls, t: gdb.Type) -> gdb.Type:
141141
# compressed types only exist for java type which are either struct or union
142142
if t.code != gdb.TYPE_CODE_STRUCT and t.code != gdb.TYPE_CODE_UNION:
143143
return t
144-
result = cls.get_base_class(t) if cls.is_compressed(t) else t
144+
result = cls.get_base_class(t) if (cls.is_compressed(t) and t != cls.hub_type) else t
145145
trace(f'<SVMUtil> - get_uncompressed_type({t}) = {result}')
146146
return result
147147

@@ -177,7 +177,7 @@ def get_compressed_oop(cls, obj: gdb.Value) -> int:
177177
# recreate compressed oop from the object address
178178
# this reverses the uncompress expression from
179179
# com.oracle.objectfile.elf.dwarf.DwarfInfoSectionImpl#writeIndirectOopConversionExpression
180-
is_hub = cls.get_rtt(obj) == cls.hub_type
180+
is_hub = cls.get_basic_type(obj.type) == cls.hub_type
181181
compression_shift = cls.compression_shift
182182
num_reserved_bits = int.bit_count(cls.reserved_bits_mask)
183183
num_alignment_bits = int.bit_count(cls.object_alignment - 1)
@@ -205,6 +205,11 @@ def get_unqualified_type_name(cls, qualified_type_name: str) -> str:
205205

206206
@classmethod
207207
def is_compressed(cls, t: gdb.Type) -> bool:
208+
# for the hub type we always want handle it as compressed as there is no clear distinction in debug info for
209+
# the hub field, and it may always have an expression in the type's data_location attribute
210+
if cls.get_basic_type(t) == cls.hub_type:
211+
return True
212+
208213
type_name = cls.get_basic_type(t).name
209214
if type_name is None:
210215
# fallback to the GDB type printer for t
@@ -363,6 +368,9 @@ def get_classloader_namespace(cls, obj: gdb.Value) -> str:
363368
def get_rtt(cls, obj: gdb.Value) -> gdb.Type:
364369
static_type = cls.get_basic_type(obj.type)
365370

371+
if static_type == cls.hub_type:
372+
return cls.hub_type
373+
366374
# check for interfaces and cast them to Object to make the hub accessible
367375
if cls.get_uncompressed_type(cls.get_basic_type(obj.type)).code == gdb.TYPE_CODE_UNION:
368376
obj = cls.cast_to(obj, cls.object_type)

substratevm/mx.substratevm/testhello.py

Lines changed: 161 additions & 76 deletions
Large diffs are not rendered by default.

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/ClassEntry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ protected MethodEntry processMethod(DebugMethodInfo debugMethodInfo, DebugInfoBa
288288
}
289289

290290
@Override
291-
protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
292-
FieldEntry fieldEntry = super.addField(debugFieldInfo, debugInfoBase, debugContext);
291+
protected FieldEntry createField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
292+
FieldEntry fieldEntry = super.createField(debugFieldInfo, debugInfoBase, debugContext);
293293
return fieldEntry;
294294
}
295295

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/DebugInfoBase.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocalValueInfo;
4747
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugLocationInfo;
4848
import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugTypeInfo.DebugTypeKind;
49-
import com.oracle.objectfile.elf.dwarf.DwarfDebugInfo;
5049

5150
import jdk.graal.compiler.debug.DebugContext;
5251
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -135,6 +134,10 @@ public abstract class DebugInfoBase {
135134
* Handle on class entry for java.lang.Object.
136135
*/
137136
private ClassEntry objectClass;
137+
/**
138+
* The type entry for java.lang.Class.
139+
*/
140+
private ClassEntry classClass;
138141
/**
139142
* List of all top level compiled methods found in debug info. These ought to arrive via the
140143
* debug info API in ascending address range order.
@@ -202,11 +205,6 @@ public abstract class DebugInfoBase {
202205
*/
203206
private int compiledCodeMax;
204207

205-
/**
206-
* The type entry for java.lang.Class.
207-
*/
208-
private ClassEntry hubClassEntry;
209-
210208
@SuppressWarnings("this-escape")
211209
public DebugInfoBase(ByteOrder byteOrder) {
212210
this.byteOrder = byteOrder;
@@ -218,7 +216,6 @@ public DebugInfoBase(ByteOrder byteOrder) {
218216
this.pointerSize = 0;
219217
this.objectAlignment = 0;
220218
this.numAlignmentBits = 0;
221-
this.hubClassEntry = null;
222219
this.compiledCodeMax = 0;
223220
// create and index an empty dir with index 0.
224221
ensureDirEntry(EMPTY_PATH);
@@ -372,9 +369,6 @@ private TypeEntry createTypeEntry(String typeName, String fileName, Path filePat
372369
case INSTANCE: {
373370
FileEntry fileEntry = addFileEntry(fileName, filePath);
374371
typeEntry = new ClassEntry(typeName, fileEntry, size);
375-
if (typeEntry.getTypeName().equals(DwarfDebugInfo.HUB_TYPE_NAME)) {
376-
hubClassEntry = (ClassEntry) typeEntry;
377-
}
378372
break;
379373
}
380374
case INTERFACE: {
@@ -423,6 +417,9 @@ private TypeEntry addTypeEntry(ResolvedJavaType idType, String typeName, String
423417
if (idType == null) {
424418
headerType = (HeaderTypeEntry) typeEntry;
425419
}
420+
if (typeName.equals("java.lang.Class")) {
421+
classClass = (ClassEntry) typeEntry;
422+
}
426423
if (typeName.equals("java.lang.Object")) {
427424
objectClass = (ClassEntry) typeEntry;
428425
}
@@ -479,6 +476,12 @@ public ClassEntry lookupObjectClass() {
479476
return objectClass;
480477
}
481478

479+
public ClassEntry lookupClassClass() {
480+
// this should only be looked up after all types have been notified
481+
assert classClass != null;
482+
return classClass;
483+
}
484+
482485
private void addPrimaryRange(PrimaryRange primaryRange, DebugCodeInfo debugCodeInfo, ClassEntry classEntry) {
483486
CompiledMethodEntry compiledMethod = classEntry.indexPrimary(primaryRange, debugCodeInfo.getFrameSizeChanges(), debugCodeInfo.getFrameSize());
484487
indexCompiledMethod(compiledMethod);
@@ -737,14 +740,6 @@ public String getCachePath() {
737740
return cachePath;
738741
}
739742

740-
public boolean isHubClassEntry(StructureTypeEntry typeEntry) {
741-
return typeEntry.getTypeName().equals(DwarfDebugInfo.HUB_TYPE_NAME);
742-
}
743-
744-
public ClassEntry getHubClassEntry() {
745-
return hubClassEntry;
746-
}
747-
748743
private static void collectFilesAndDirs(ClassEntry classEntry) {
749744
// track files and dirs we have already seen so that we only add them once
750745
EconomicSet<FileEntry> visitedFiles = EconomicSet.create();

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/HeaderTypeEntry.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@
3434

3535
public class HeaderTypeEntry extends StructureTypeEntry {
3636

37+
FieldEntry hubField;
38+
3739
public HeaderTypeEntry(String typeName, int size) {
3840
super(typeName, size);
3941
}
4042

43+
public FieldEntry getHubField() {
44+
return hubField;
45+
}
46+
4147
@Override
4248
public DebugTypeKind typeKind() {
4349
return DebugTypeKind.HEADER;
@@ -49,5 +55,6 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf
4955
assert debugTypeInfo.typeName().equals(typeName);
5056
DebugHeaderTypeInfo debugHeaderTypeInfo = (DebugHeaderTypeInfo) debugTypeInfo;
5157
debugHeaderTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext));
58+
hubField = createField(debugHeaderTypeInfo.hubField(), debugInfoBase, debugContext);
5259
}
5360
}

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debugentry/StructureTypeEntry.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ public int fieldCount() {
7575

7676
protected void processField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
7777
/* Delegate this so superclasses can override this and inspect the computed FieldEntry. */
78-
addField(debugFieldInfo, debugInfoBase, debugContext);
78+
FieldEntry fieldEntry = createField(debugFieldInfo, debugInfoBase, debugContext);
79+
fields.add(fieldEntry);
7980
}
8081

81-
protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
82+
protected FieldEntry createField(DebugFieldInfo debugFieldInfo, DebugInfoBase debugInfoBase, DebugContext debugContext) {
8283
String fieldName = debugInfoBase.uniqueDebugString(debugFieldInfo.name());
8384
ResolvedJavaType valueType = debugFieldInfo.valueType();
8485
String valueTypeName = valueType.toJavaName();
@@ -96,9 +97,7 @@ protected FieldEntry addField(DebugFieldInfo debugFieldInfo, DebugInfoBase debug
9697
* substitution
9798
*/
9899
FileEntry fileEntry = debugInfoBase.ensureFileEntry(debugFieldInfo);
99-
FieldEntry fieldEntry = new FieldEntry(fileEntry, fieldName, this, valueTypeEntry, fieldSize, fieldoffset, fieldIsEmbedded, fieldModifiers);
100-
fields.add(fieldEntry);
101-
return fieldEntry;
100+
return new FieldEntry(fileEntry, fieldName, this, valueTypeEntry, fieldSize, fieldoffset, fieldIsEmbedded, fieldModifiers);
102101
}
103102

104103
String memberModifiers(int modifiers) {

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/debuginfo/DebugInfoProvider.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ interface DebugPrimitiveTypeInfo extends DebugTypeInfo {
219219
interface DebugHeaderTypeInfo extends DebugTypeInfo {
220220

221221
Stream<DebugFieldInfo> fieldInfoProvider();
222+
223+
DebugFieldInfo hubField();
222224
}
223225

224226
interface DebugMemberInfo extends DebugFileInfo {

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfAbbrevSectionImpl.java

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -936,8 +936,7 @@ public int writeAbbrevs(DebugContext context, byte[] buffer, int p) {
936936
pos = writeForeignTypedefAbbrev(context, buffer, pos);
937937
pos = writeForeignStructAbbrev(context, buffer, pos);
938938

939-
pos = writeHeaderFieldAbbrev(context, buffer, pos);
940-
pos = writeArrayElementFieldAbbrev(context, buffer, pos);
939+
pos = writeFieldAbbrevs(context, buffer, pos);
941940
pos = writeArrayDataTypeAbbrevs(context, buffer, pos);
942941
pos = writeArraySubrangeTypeAbbrev(context, buffer, pos);
943942
pos = writeMethodLocationAbbrev(context, buffer, pos);
@@ -957,10 +956,11 @@ public int writeAbbrevs(DebugContext context, byte[] buffer, int p) {
957956
*
958957
* if address rebasing is not required then a data_location attribute on the layout type
959958
* will ensure that address tag bits are removed.
959+
*
960+
* The compressed layout is also used for representing the decode step for dynamic hubs.
961+
* I.e. this is also required for builds without isolates
960962
*/
961-
if (dwarfSections.useHeapBase()) {
962-
pos = writeCompressedLayoutAbbrev(context, buffer, pos);
963-
}
963+
pos = writeCompressedLayoutAbbrev(context, buffer, pos);
964964

965965
pos = writeParameterDeclarationAbbrevs(context, buffer, pos);
966966
pos = writeLocalDeclarationAbbrevs(context, buffer, pos);
@@ -1114,12 +1114,9 @@ private int writeNamespaceAbbrev(@SuppressWarnings("unused") DebugContext contex
11141114

11151115
private int writeClassLayoutAbbrevs(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
11161116
int pos = p;
1117-
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_1, buffer, pos);
1118-
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_3, buffer, pos);
1119-
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_4, buffer, pos);
1120-
if (!dwarfSections.useHeapBase()) {
1121-
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_2, buffer, pos);
1122-
}
1117+
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_TU, buffer, pos);
1118+
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_CU, buffer, pos);
1119+
pos = writeClassLayoutAbbrev(context, AbbrevCode.CLASS_LAYOUT_ARRAY, buffer, pos);
11231120
return pos;
11241121
}
11251122

@@ -1131,12 +1128,12 @@ private int writeClassLayoutAbbrev(@SuppressWarnings("unused") DebugContext cont
11311128
pos = writeHasChildren(DwarfHasChildren.DW_CHILDREN_yes, buffer, pos);
11321129
pos = writeAttrType(DwarfAttribute.DW_AT_name, buffer, pos);
11331130
pos = writeAttrForm(DwarfForm.DW_FORM_strp, buffer, pos);
1134-
if (abbrevCode == AbbrevCode.CLASS_LAYOUT_3 || abbrevCode == AbbrevCode.CLASS_LAYOUT_4) {
1131+
if (abbrevCode == AbbrevCode.CLASS_LAYOUT_ARRAY || abbrevCode == AbbrevCode.CLASS_LAYOUT_CU) {
11351132
pos = writeAttrType(DwarfAttribute.DW_AT_declaration, buffer, pos);
11361133
pos = writeAttrForm(DwarfForm.DW_FORM_flag, buffer, pos);
11371134
pos = writeAttrType(DwarfAttribute.DW_AT_signature, buffer, pos);
11381135
pos = writeAttrForm(DwarfForm.DW_FORM_ref_sig8, buffer, pos);
1139-
if (abbrevCode == AbbrevCode.CLASS_LAYOUT_4) {
1136+
if (abbrevCode == AbbrevCode.CLASS_LAYOUT_CU) {
11401137
pos = writeAttrType(DwarfAttribute.DW_AT_decl_file, buffer, pos);
11411138
pos = writeAttrForm(DwarfForm.DW_FORM_data2, buffer, pos);
11421139
/*-
@@ -1148,10 +1145,6 @@ private int writeClassLayoutAbbrev(@SuppressWarnings("unused") DebugContext cont
11481145
} else {
11491146
pos = writeAttrType(DwarfAttribute.DW_AT_byte_size, buffer, pos);
11501147
pos = writeAttrForm(DwarfForm.DW_FORM_data2, buffer, pos);
1151-
if (abbrevCode == AbbrevCode.CLASS_LAYOUT_2) {
1152-
pos = writeAttrType(DwarfAttribute.DW_AT_data_location, buffer, pos);
1153-
pos = writeAttrForm(DwarfForm.DW_FORM_expr_loc, buffer, pos);
1154-
}
11551148
}
11561149
/*
11571150
* Now terminate.
@@ -1409,38 +1402,27 @@ private int writeForeignStructAbbrev(@SuppressWarnings("unused") DebugContext co
14091402
return pos;
14101403
}
14111404

1412-
private int writeHeaderFieldAbbrev(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
1405+
private int writeFieldAbbrevs(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
14131406
int pos = p;
1414-
1415-
pos = writeAbbrevCode(AbbrevCode.HEADER_FIELD, buffer, pos);
1416-
pos = writeTag(DwarfTag.DW_TAG_member, buffer, pos);
1417-
pos = writeHasChildren(DwarfHasChildren.DW_CHILDREN_no, buffer, pos);
1418-
pos = writeAttrType(DwarfAttribute.DW_AT_name, buffer, pos);
1419-
pos = writeAttrForm(DwarfForm.DW_FORM_strp, buffer, pos);
1420-
pos = writeAttrType(DwarfAttribute.DW_AT_type, buffer, pos);
1421-
pos = writeAttrForm(DwarfForm.DW_FORM_ref_sig8, buffer, pos);
1422-
pos = writeAttrType(DwarfAttribute.DW_AT_data_member_location, buffer, pos);
1423-
pos = writeAttrForm(DwarfForm.DW_FORM_data2, buffer, pos);
1424-
pos = writeAttrType(DwarfAttribute.DW_AT_accessibility, buffer, pos);
1425-
pos = writeAttrForm(DwarfForm.DW_FORM_data1, buffer, pos);
1426-
/*
1427-
* Now terminate.
1428-
*/
1429-
pos = writeAttrType(DwarfAttribute.DW_AT_null, buffer, pos);
1430-
pos = writeAttrForm(DwarfForm.DW_FORM_null, buffer, pos);
1407+
pos = writeFieldAbbrev(context, AbbrevCode.STRUCT_FIELD_SIG, buffer, pos);
1408+
pos = writeFieldAbbrev(context, AbbrevCode.STRUCT_FIELD, buffer, pos);
14311409
return pos;
14321410
}
14331411

1434-
private int writeArrayElementFieldAbbrev(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
1412+
private int writeFieldAbbrev(@SuppressWarnings("unused") DebugContext context, AbbrevCode abbrevCode, byte[] buffer, int p) {
14351413
int pos = p;
14361414

1437-
pos = writeAbbrevCode(AbbrevCode.ARRAY_ELEMENT_FIELD, buffer, pos);
1415+
pos = writeAbbrevCode(abbrevCode, buffer, pos);
14381416
pos = writeTag(DwarfTag.DW_TAG_member, buffer, pos);
14391417
pos = writeHasChildren(DwarfHasChildren.DW_CHILDREN_no, buffer, pos);
14401418
pos = writeAttrType(DwarfAttribute.DW_AT_name, buffer, pos);
14411419
pos = writeAttrForm(DwarfForm.DW_FORM_strp, buffer, pos);
14421420
pos = writeAttrType(DwarfAttribute.DW_AT_type, buffer, pos);
1443-
pos = writeAttrForm(DwarfForm.DW_FORM_ref_addr, buffer, pos);
1421+
if (abbrevCode == AbbrevCode.STRUCT_FIELD_SIG) {
1422+
pos = writeAttrForm(DwarfForm.DW_FORM_ref_sig8, buffer, pos);
1423+
} else {
1424+
pos = writeAttrForm(DwarfForm.DW_FORM_ref_addr, buffer, pos);
1425+
}
14441426
pos = writeAttrType(DwarfAttribute.DW_AT_data_member_location, buffer, pos);
14451427
pos = writeAttrForm(DwarfForm.DW_FORM_data2, buffer, pos);
14461428
pos = writeAttrType(DwarfAttribute.DW_AT_accessibility, buffer, pos);

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfDebugInfo.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,9 @@ enum AbbrevCode {
6767
OBJECT_HEADER,
6868
CLASS_CONSTANT,
6969
NAMESPACE,
70-
CLASS_LAYOUT_1,
71-
CLASS_LAYOUT_2,
72-
CLASS_LAYOUT_3,
73-
CLASS_LAYOUT_4,
70+
CLASS_LAYOUT_TU,
71+
CLASS_LAYOUT_CU,
72+
CLASS_LAYOUT_ARRAY,
7473
TYPE_POINTER_SIG,
7574
TYPE_POINTER,
7675
FOREIGN_TYPEDEF,
@@ -88,8 +87,8 @@ enum AbbrevCode {
8887
FIELD_DECLARATION_2,
8988
FIELD_DECLARATION_3,
9089
FIELD_DECLARATION_4,
91-
HEADER_FIELD,
92-
ARRAY_ELEMENT_FIELD,
90+
STRUCT_FIELD_SIG,
91+
STRUCT_FIELD,
9392
ARRAY_DATA_TYPE_1,
9493
ARRAY_DATA_TYPE_2,
9594
ARRAY_SUBRANGE,
@@ -140,7 +139,7 @@ enum AbbrevCode {
140139
* The name of the type for header field hub which needs special case processing to remove tag
141140
* bits
142141
*/
143-
public static final String HUB_TYPE_NAME = "java.lang.Class";
142+
public static final String HUB_TYPE_NAME = "Encoded$Dynamic$Hub";
144143
/* Full byte/word values. */
145144
private final DwarfStrSectionImpl dwarfStrSection;
146145
private final DwarfAbbrevSectionImpl dwarfAbbrevSection;

0 commit comments

Comments
 (0)