Skip to content

Commit 6ce58a6

Browse files
committed
[GR-41047] Use C++ symbol mangling on Linux to make tools happy
PullRequest: graal/12671
2 parents 3a4ef1f + 3d15b72 commit 6ce58a6

21 files changed

+1305
-175
lines changed

substratevm/mx.substratevm/testhello.py

Lines changed: 70 additions & 66 deletions
Large diffs are not rendered by default.

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,15 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf
6161
public TypeEntry getElementType() {
6262
return elementType;
6363
}
64+
65+
public String getLoaderId() {
66+
TypeEntry type = elementType;
67+
while (type.isArray()) {
68+
type = ((ArrayTypeEntry) type).elementType;
69+
}
70+
if (type.isClass()) {
71+
return ((ClassEntry) type).getLoaderId();
72+
}
73+
return "";
74+
}
6475
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public class ClassEntry extends StructureTypeEntry {
6262
* Details of the associated file.
6363
*/
6464
private FileEntry fileEntry;
65+
/**
66+
* Details of the associated loader.
67+
*/
68+
private LoaderEntry loader;
6569
/**
6670
* Details of methods located in this instance.
6771
*/
@@ -108,6 +112,7 @@ public ClassEntry(String className, FileEntry fileEntry, int size) {
108112
super(className, size);
109113
this.interfaces = new ArrayList<>();
110114
this.fileEntry = fileEntry;
115+
this.loader = null;
111116
this.methods = new ArrayList<>();
112117
this.methodsIndex = new HashMap<>();
113118
this.normalCompiledEntries = new ArrayList<>();
@@ -150,6 +155,10 @@ public void addDebugInfo(DebugInfoBase debugInfoBase, DebugTypeInfo debugTypeInf
150155
if (superType != null) {
151156
this.superClass = debugInfoBase.lookupClassEntry(superType);
152157
}
158+
String loaderName = debugInstanceTypeInfo.loaderName();
159+
if (!loaderName.isEmpty()) {
160+
this.loader = debugInfoBase.ensureLoaderEntry(loaderName);
161+
}
153162
debugInstanceTypeInfo.interfaces().forEach(interfaceType -> processInterface(interfaceType, debugInfoBase, debugContext));
154163
/* Add details of fields and field types */
155164
debugInstanceTypeInfo.fieldInfoProvider().forEach(debugFieldInfo -> this.processField(debugFieldInfo, debugInfoBase, debugContext));
@@ -256,6 +265,10 @@ public FileEntry getFileEntry() {
256265
return fileEntry;
257266
}
258267

268+
public String getLoaderId() {
269+
return (loader != null ? loader.getLoaderId() : "");
270+
}
271+
259272
/**
260273
* Retrieve a stream of all compiled method entries for this class, including both normal and
261274
* deopt fallback compiled methods.

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ public abstract class DebugInfoBase {
141141
* Index of files which contain primary or secondary ranges keyed by path.
142142
*/
143143
private Map<Path, FileEntry> filesIndex = new HashMap<>();
144+
145+
/**
146+
* List of all loaders associated with classes included in the image.
147+
*/
148+
private List<LoaderEntry> loaders = new ArrayList<>();
149+
150+
/**
151+
* Index of all loaders associated with classes included in the image.
152+
*/
153+
private Map<String, LoaderEntry> loaderIndex = new HashMap<>();
154+
144155
/**
145156
* Flag set to true if heap references are stored as addresses relative to a heap base register
146157
* otherwise false.
@@ -501,6 +512,15 @@ private DirEntry ensureDirEntry(Path filePath) {
501512
return dirEntry;
502513
}
503514

515+
protected LoaderEntry ensureLoaderEntry(String loaderId) {
516+
LoaderEntry loaderEntry = loaderIndex.get(loaderId);
517+
if (loaderEntry == null) {
518+
loaderEntry = new LoaderEntry(uniqueDebugString(loaderId));
519+
loaderIndex.put(loaderEntry.getLoaderId(), loaderEntry);
520+
}
521+
return loaderEntry;
522+
}
523+
504524
/* Accessors to query the debug info model. */
505525
public ByteOrder getByteOrder() {
506526
return byteOrder;
@@ -524,6 +544,15 @@ public FileEntry findFile(Path fullFileName) {
524544
return filesIndex.get(fullFileName);
525545
}
526546

547+
public List<LoaderEntry> getLoaders() {
548+
return loaders;
549+
}
550+
551+
@SuppressWarnings("unused")
552+
public LoaderEntry findLoader(String id) {
553+
return loaderIndex.get(id);
554+
}
555+
527556
public StringTable getStringTable() {
528557
return stringTable;
529558
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2020, 2020, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package com.oracle.objectfile.debugentry;
27+
28+
/**
29+
* A LoaderEntry is used to record a unique id string for the class loader asscoiated with classes
30+
* that can be susceptible to repeat definitions. In such cases the loader id can be used when
31+
* constructing a unique linker symbol for methods and static fields of the class. That same id may
32+
* need to be embedded in debug info that identifies class and method names.
33+
*/
34+
public class LoaderEntry {
35+
String loaderId;
36+
37+
public LoaderEntry(String id) {
38+
loaderId = id;
39+
}
40+
41+
public String getLoaderId() {
42+
return loaderId;
43+
}
44+
}

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
@@ -138,6 +138,8 @@ public String toString() {
138138
public interface DebugInstanceTypeInfo extends DebugTypeInfo {
139139
int headerSize();
140140

141+
String loaderName();
142+
141143
Stream<DebugFieldInfo> fieldInfoProvider();
142144

143145
Stream<DebugMethodInfo> methodInfoProvider();

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

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ public void createContent() {
154154
* instance fields. They are not needed when typing local vars and parameters held in
155155
* registers or on the stack as they appear as raw addresses.
156156
*
157+
* <li><code>code = namespace, tag = namespace, parent = class_unit, array_unit,
158+
* interface_unit<code> - a wrap-around DIE that is used to embed all the normal level 1
159+
* DIEs of a <code>class_unit</code> or <code>array_unit</code_unit> in a namespace. This is
160+
* needed when the corresponding class/interface or array base element type have been loaded
161+
* by a loader with a non-empty loader in order to ensure that mangled names for the class
162+
* and its members can legitimately employ the loader id as a namespace prefix. Note that
163+
* use of a namespace wrapper DIE causes all the embedded level 1+ DIEs documented above and
164+
* all their children to be generated at a level one greater than documented here.
165+
*
157166
* </ul>
158167
*
159168
* <ul>
@@ -198,7 +207,18 @@ public void createContent() {
198207
*
199208
* Details of each specific DIE contents are as follows:
200209
*
201-
* Primitive Types: For each non-void Java primitive type there is a level 0 DIE defining a
210+
* A single instance of the level 0 <code>builtin_unit</code> compile unit provides details
211+
* of all Java primitive types and of the struct type which describes the layout of object
212+
* headers, including array headers.
213+
*
214+
* <li><code>abbrev_code == builtin_unit, tag == DW_TAG_compilation_unit,
215+
* has_children</code>
216+
*
217+
* <li><code>DW_AT_language : ... DW_FORM_data1</code>
218+
*
219+
* </ul>
220+
*
221+
* Primitive Types: For each non-void Java primitive type there is a level 1 DIE defining a
202222
* base type
203223
*
204224
* <ul>
@@ -225,7 +245,7 @@ public void createContent() {
225245
*
226246
* </ul>
227247
*
228-
* Header: There is a level 0 DIE defining structure types used to define the various types
248+
* Header: There is a level 1 DIE defining structure types used to define the various types
229249
* of header structure embedded at the start of every instance or array. All instances embed
230250
* the same object header. Array headers embed the object header as a parent type, allowing
231251
* an array to be viewed as a type of object. Multiple array headers structures are defined
@@ -243,7 +263,7 @@ public void createContent() {
243263
*
244264
* </ul>
245265
*
246-
* Header Data: A level 1 DIE of type member is used to describe the fields of both object
266+
* Header Data: A level 2 DIE of type member is used to describe the fields of both object
247267
* and array headers. This includes the type tag and other tag bits in all objects, the
248268
* length field in all arrays and any padding bytes needed to complete the layout.
249269
*
@@ -290,6 +310,20 @@ public void createContent() {
290310
*
291311
* </ul>
292312
*
313+
* Namespace embedding:
314+
*
315+
* When the class loader associated with a class defined in a <code>class_unit</code>
316+
* compile unit has a non-empty loader id string then a namespace DIE is used to wrap all
317+
* its child DIEs. Otherwise the children are embedded directly. The namespace DIE has a
318+
* single attribute defining the namespace's name as the loader id string.
319+
*
320+
* <li><code>abbrev_code == namespace, tag == DW_TAG_namespace, has_children</code>
321+
*
322+
* <li><code>DW_AT_name : ....... DW_FORM_strp</code>
323+
*
324+
* </ul>
325+
*
326+
*
293327
* Instance Class Structure: Each class_unit DIE contains a series of level 1 DIEs. The
294328
* first one describes the class layout. The normal layout does not include a data_location
295329
* attribute. However, an alternative layout, including that extra attribute, is provided to
@@ -663,10 +697,15 @@ public void createContent() {
663697
*
664698
* Array Structure: Each array_unit DIE contains four level 1 DIEs. The first one describes
665699
* the array layout. It has only one child, a super_reference DIE (see above) that
666-
* references the appropriate array header type for an obnject aray or primitive array of
700+
* references the appropriate array header type for an object array or primitive array of
667701
* the relevant primitive type). The size of the array layout is the same as the size of the
668702
* array header.
669703
*
704+
* Note that when the base element type of the array is a class whose loader has an
705+
* associated loader id the array's children are embedded in a namespace DIE. This is needed
706+
* because the encoded type name for the array will include a namespace prefix in order to
707+
* guarantee that it remains unique.
708+
*
670709
* <ul>
671710
*
672711
* <li><code>abbrev_code == array_layout, tag == DW_TAG_class_type, has_children</code>
@@ -825,6 +864,8 @@ public int writeAbbrevs(DebugContext context, byte[] buffer, int p) {
825864
pos = writeVoidTypeAbbrev(context, buffer, pos);
826865
pos = writeObjectHeaderAbbrev(context, buffer, pos);
827866

867+
pos = writeNamespaceAbbrev(context, buffer, pos);
868+
828869
pos = writeClassLayoutAbbrevs(context, buffer, pos);
829870
pos = writeClassReferenceAbbrev(context, buffer, pos);
830871
pos = writeMethodDeclarationAbbrevs(context, buffer, pos);
@@ -1002,6 +1043,21 @@ private int writeObjectHeaderAbbrev(@SuppressWarnings("unused") DebugContext con
10021043
return pos;
10031044
}
10041045

1046+
private int writeNamespaceAbbrev(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
1047+
int pos = p;
1048+
pos = writeAbbrevCode(DwarfDebugInfo.DW_ABBREV_CODE_namespace, buffer, pos);
1049+
pos = writeTag(DwarfDebugInfo.DW_TAG_namespace, buffer, pos);
1050+
pos = writeFlag(DwarfDebugInfo.DW_CHILDREN_yes, buffer, pos);
1051+
pos = writeAttrType(DwarfDebugInfo.DW_AT_name, buffer, pos);
1052+
pos = writeAttrForm(DwarfDebugInfo.DW_FORM_strp, buffer, pos);
1053+
/*
1054+
* Now terminate.
1055+
*/
1056+
pos = writeAttrType(DwarfDebugInfo.DW_AT_null, buffer, pos);
1057+
pos = writeAttrForm(DwarfDebugInfo.DW_FORM_null, buffer, pos);
1058+
return pos;
1059+
}
1060+
10051061
private int writeClassLayoutAbbrevs(@SuppressWarnings("unused") DebugContext context, byte[] buffer, int p) {
10061062
int pos = p;
10071063
pos = writeClassLayoutAbbrev(context, DwarfDebugInfo.DW_ABBREV_CODE_class_layout1, buffer, pos);

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

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -78,43 +78,44 @@ public class DwarfDebugInfo extends DebugInfoBase {
7878
public static final int DW_ABBREV_CODE_primitive_type = 5;
7979
public static final int DW_ABBREV_CODE_void_type = 6;
8080
public static final int DW_ABBREV_CODE_object_header = 7;
81-
public static final int DW_ABBREV_CODE_class_layout1 = 8;
82-
public static final int DW_ABBREV_CODE_class_layout2 = 9;
83-
public static final int DW_ABBREV_CODE_class_pointer = 10;
84-
public static final int DW_ABBREV_CODE_method_location = 11;
85-
public static final int DW_ABBREV_CODE_abstract_inline_method = 12;
86-
public static final int DW_ABBREV_CODE_static_field_location = 13;
87-
public static final int DW_ABBREV_CODE_array_layout = 14;
88-
public static final int DW_ABBREV_CODE_array_pointer = 15;
89-
public static final int DW_ABBREV_CODE_interface_layout = 16;
90-
public static final int DW_ABBREV_CODE_interface_pointer = 17;
91-
public static final int DW_ABBREV_CODE_indirect_layout = 18;
92-
public static final int DW_ABBREV_CODE_indirect_pointer = 19;
81+
public static final int DW_ABBREV_CODE_namespace = 8;
82+
public static final int DW_ABBREV_CODE_class_layout1 = 9;
83+
public static final int DW_ABBREV_CODE_class_layout2 = 10;
84+
public static final int DW_ABBREV_CODE_class_pointer = 11;
85+
public static final int DW_ABBREV_CODE_method_location = 12;
86+
public static final int DW_ABBREV_CODE_abstract_inline_method = 13;
87+
public static final int DW_ABBREV_CODE_static_field_location = 14;
88+
public static final int DW_ABBREV_CODE_array_layout = 15;
89+
public static final int DW_ABBREV_CODE_array_pointer = 16;
90+
public static final int DW_ABBREV_CODE_interface_layout = 17;
91+
public static final int DW_ABBREV_CODE_interface_pointer = 18;
92+
public static final int DW_ABBREV_CODE_indirect_layout = 19;
93+
public static final int DW_ABBREV_CODE_indirect_pointer = 20;
9394
/* Level 2 DIEs. */
94-
public static final int DW_ABBREV_CODE_method_declaration = 20;
95-
public static final int DW_ABBREV_CODE_method_declaration_static = 21;
96-
public static final int DW_ABBREV_CODE_field_declaration1 = 22;
97-
public static final int DW_ABBREV_CODE_field_declaration2 = 23;
98-
public static final int DW_ABBREV_CODE_field_declaration3 = 24;
99-
public static final int DW_ABBREV_CODE_field_declaration4 = 25;
100-
public static final int DW_ABBREV_CODE_header_field = 26;
101-
public static final int DW_ABBREV_CODE_array_data_type = 27;
102-
public static final int DW_ABBREV_CODE_super_reference = 28;
103-
public static final int DW_ABBREV_CODE_interface_implementor = 29;
95+
public static final int DW_ABBREV_CODE_method_declaration = 21;
96+
public static final int DW_ABBREV_CODE_method_declaration_static = 22;
97+
public static final int DW_ABBREV_CODE_field_declaration1 = 23;
98+
public static final int DW_ABBREV_CODE_field_declaration2 = 24;
99+
public static final int DW_ABBREV_CODE_field_declaration3 = 25;
100+
public static final int DW_ABBREV_CODE_field_declaration4 = 26;
101+
public static final int DW_ABBREV_CODE_header_field = 27;
102+
public static final int DW_ABBREV_CODE_array_data_type = 28;
103+
public static final int DW_ABBREV_CODE_super_reference = 29;
104+
public static final int DW_ABBREV_CODE_interface_implementor = 30;
104105
/* Level 2+K DIEs (where inline depth K >= 0) */
105-
public static final int DW_ABBREV_CODE_inlined_subroutine = 30;
106-
public static final int DW_ABBREV_CODE_inlined_subroutine_with_children = 31;
106+
public static final int DW_ABBREV_CODE_inlined_subroutine = 31;
107+
public static final int DW_ABBREV_CODE_inlined_subroutine_with_children = 32;
107108
/* Level 2 DIEs. */
108-
public static final int DW_ABBREV_CODE_method_parameter_declaration1 = 32;
109-
public static final int DW_ABBREV_CODE_method_parameter_declaration2 = 33;
110-
public static final int DW_ABBREV_CODE_method_parameter_declaration3 = 34;
111-
public static final int DW_ABBREV_CODE_method_local_declaration1 = 35;
112-
public static final int DW_ABBREV_CODE_method_local_declaration2 = 36;
109+
public static final int DW_ABBREV_CODE_method_parameter_declaration1 = 33;
110+
public static final int DW_ABBREV_CODE_method_parameter_declaration2 = 34;
111+
public static final int DW_ABBREV_CODE_method_parameter_declaration3 = 35;
112+
public static final int DW_ABBREV_CODE_method_local_declaration1 = 36;
113+
public static final int DW_ABBREV_CODE_method_local_declaration2 = 37;
113114
/* Level 3 DIEs. */
114-
public static final int DW_ABBREV_CODE_method_parameter_location1 = 37;
115-
public static final int DW_ABBREV_CODE_method_parameter_location2 = 38;
116-
public static final int DW_ABBREV_CODE_method_local_location1 = 39;
117-
public static final int DW_ABBREV_CODE_method_local_location2 = 40;
115+
public static final int DW_ABBREV_CODE_method_parameter_location1 = 38;
116+
public static final int DW_ABBREV_CODE_method_parameter_location2 = 39;
117+
public static final int DW_ABBREV_CODE_method_local_location1 = 40;
118+
public static final int DW_ABBREV_CODE_method_local_location2 = 41;
118119

119120
/*
120121
* Define all the Dwarf tags we need for our DIEs.
@@ -131,6 +132,7 @@ public class DwarfDebugInfo extends DebugInfoBase {
131132
public static final int DW_TAG_base_type = 0x24;
132133
public static final int DW_TAG_subprogram = 0x2e;
133134
public static final int DW_TAG_variable = 0x34;
135+
public static final int DW_TAG_namespace = 0x39;
134136
public static final int DW_TAG_unspecified_type = 0x3b;
135137
public static final int DW_TAG_inlined_subroutine = 0x1d;
136138

@@ -208,6 +210,11 @@ public class DwarfDebugInfo extends DebugInfoBase {
208210
* Value for DW_AT_language attribute with form DATA1.
209211
*/
210212
public static final byte DW_LANG_Java = 0xb;
213+
/**
214+
* This field defines the value used for the DW_AT_language attribute of compile units.
215+
*
216+
*/
217+
public static final byte LANG_ENCODING = DW_LANG_Java;
211218
/*
212219
* Values for {@link DW_AT_inline} attribute with form DATA1.
213220
*/

0 commit comments

Comments
 (0)