Skip to content

Commit 819be3a

Browse files
sstricklCommit Queue
authored andcommitted
---
yaml --- r: 361485 b: refs/heads/main c: 3b2c41d h: refs/heads/main i: 361483: 982cd0c
1 parent 222b068 commit 819be3a

File tree

9 files changed

+678
-426
lines changed

9 files changed

+678
-426
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ refs/tags/2.14.0-96.0.dev: 1eee24e50fc3028754d9a8e98852b949c04da4e4
19881988
refs/tags/2.14.0-97.0.dev: ba9c1636e87fbdcc02b8bc4a584455c32f8378b4
19891989
refs/tags/2.14.0-98.0.dev: f2d370c93582bbf4da42b5dd4c906d6145b01ea9
19901990
refs/tags/2.14.0-99.0.dev: e722f62b48fb382534efc1f20735def68848006f
1991-
refs/heads/main: e77f2ee5ffe37173cfdac0ffe79ae20c25399ec8
1991+
refs/heads/main: 3b2c41d789aa7aa122c7ff6a33f63b8073717b88
19921992
refs/heads/TedSander-patch-1: 739563c962fea6f5e2883a8d84f8638c48f2aa40
19931993
refs/tags/2.13.1: 53a67a7b0650edb435535a50b5c430abbc68bc60
19941994
refs/tags/2.13.3: a77223333944631f8f48a76e7f4697a4877e29d7

trunk/runtime/tests/vm/dart/use_add_readonly_data_symbols_flag_test.dart

Lines changed: 143 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@ main(List<String> args) async {
6262
scriptDill,
6363
]);
6464

65-
checkElf(scriptSnapshot);
66-
checkElf(scriptDebuggingInfo);
65+
final snapshotElf = Elf.fromFile(scriptSnapshot);
66+
Expect.isNotNull(snapshotElf);
67+
final debugInfoElf = Elf.fromFile(scriptDebuggingInfo);
68+
Expect.isNotNull(debugInfoElf);
6769

68-
if (Platform.isLinux && !isSimulator) {
70+
checkElf(snapshotElf!, debugInfoElf!, isAssembled: false);
71+
72+
if ((Platform.isLinux || Platform.isMacOS) && !isSimulator) {
6973
final scriptAssembly = path.join(tempDir, 'snapshot.S');
7074
final scriptAssemblySnapshot = path.join(tempDir, 'assembly.so');
7175
final scriptAssemblyDebuggingInfo =
@@ -83,63 +87,57 @@ main(List<String> args) async {
8387
await assembleSnapshot(scriptAssembly, scriptAssemblySnapshot,
8488
debug: true);
8589

86-
checkElf(scriptAssemblySnapshot, isAssembled: true);
87-
checkElf(scriptAssemblyDebuggingInfo);
90+
// This one may be null if on MacOS.
91+
final assembledElf = Elf.fromFile(scriptAssemblySnapshot);
92+
if (Platform.isLinux) {
93+
Expect.isNotNull(assembledElf);
94+
}
95+
final assembledDebugElf = Elf.fromFile(scriptAssemblyDebuggingInfo);
96+
Expect.isNotNull(assembledDebugElf);
97+
98+
checkElf(assembledElf, assembledDebugElf!, isAssembled: true);
8899
}
89100
});
90101
}
91102

92-
void checkElf(String filename, {bool isAssembled = false}) {
93-
// Check that the static symbol table contains entries that are not in the
94-
// dynamic symbol table, have STB_LOCAL binding, and are of type STT_OBJECT.
95-
final elf = Elf.fromFile(filename);
96-
Expect.isNotNull(elf);
97-
final dynamicSymbols = elf!.dynamicSymbols;
98-
// All symbol tables have an initial entry with zero-valued fields.
99-
Expect.isNotEmpty(dynamicSymbols);
100-
print('Dynamic symbols:');
101-
final initialDynamic = dynamicSymbols.first;
102-
print(initialDynamic);
103-
Expect.equals(SymbolBinding.STB_LOCAL, initialDynamic.bind);
104-
Expect.equals(SymbolType.STT_NOTYPE, initialDynamic.type);
105-
Expect.equals(0, initialDynamic.value);
106-
for (final symbol in dynamicSymbols.skip(1)) {
103+
final _uniqueSuffixRegexp = RegExp(r' \(#\d+\)');
104+
105+
void checkVMSymbolsAreValid(Iterable<Symbol> symbols,
106+
{required String source, required bool isAssembled}) {
107+
print("Checking VM symbols from $source:");
108+
for (final symbol in symbols) {
107109
print(symbol);
108-
if (!symbol.name.startsWith('_kDart')) {
109-
// The VM only adds symbols with names starting with _kDart, so this
110-
// must be an assembled snapshot.
111-
Expect.isTrue(isAssembled);
110+
// All VM-created symbols should have sizes.
111+
Expect.notEquals(0, symbol.size);
112+
if (symbol.bind != SymbolBinding.STB_GLOBAL &&
113+
symbol.bind != SymbolBinding.STB_LOCAL) {
114+
Expect.fail('Unexpected symbol binding ${symbol.bind}');
115+
}
116+
if (symbol.bind == SymbolBinding.STB_GLOBAL) {
117+
// All global symbols created by the VM are currently object symbols.
118+
Expect.equals(SymbolType.STT_OBJECT, symbol.type);
119+
Expect.isTrue(symbol.name.startsWith('_kDart'),
120+
'Unexpected symbol name ${symbol.name}');
121+
Expect.isFalse(_uniqueSuffixRegexp.hasMatch(symbol.name),
122+
'Global VM symbols should have no numeric suffix');
112123
continue;
113124
}
114-
Expect.equals(SymbolBinding.STB_GLOBAL, symbol.bind);
115-
Expect.equals(SymbolType.STT_OBJECT, symbol.type);
116-
// All VM-generated read-only object symbols should have a non-zero size.
117-
Expect.notEquals(0, symbol.size);
118-
}
119-
print("");
120-
final onlyStaticSymbols = elf.staticSymbols
121-
.where((s1) => !dynamicSymbols.any((s2) => s1.name == s2.name));
122-
Expect.isNotEmpty(onlyStaticSymbols, 'no static-only symbols');
123-
final objectSymbols =
124-
onlyStaticSymbols.where((s) => s.type == SymbolType.STT_OBJECT);
125-
Expect.isNotEmpty(objectSymbols, 'no static-only object symbols');
126-
print("Static-only object symbols:");
127-
for (final symbol in objectSymbols) {
128-
print(symbol);
129-
// There should be no static-only global object symbols.
130-
Expect.equals(SymbolBinding.STB_LOCAL, symbol.bind);
131-
final objectTypeEnd = symbol.name.indexOf('_');
132-
// All VM-generated read-only object symbols are prefixed with the type of
133-
// the C++ object followed by an underscore. If assembling the snapshot,
134-
// the assembler might introduce other object symbols which either start
135-
// with an underscore or have no underscore.
136-
if (objectTypeEnd <= 0) {
137-
Expect.isTrue(isAssembled);
125+
if (symbol.type == SymbolType.STT_FUNC ||
126+
symbol.type == SymbolType.STT_SECTION) {
127+
// Currently we don't do any additional checking on these.
138128
continue;
139129
}
140-
// All VM-generated read-only object symbols should have a non-zero size.
141-
Expect.notEquals(0, symbol.size);
142-
final objectType = symbol.name.substring(0, objectTypeEnd);
130+
if (symbol.type != SymbolType.STT_OBJECT) {
131+
Expect.fail('Unexpected symbol type ${symbol.type}');
132+
}
133+
// The name of object symbols are prefixed with the type of the object. If
134+
// there is useful additional information, the additional information is
135+
// provided after the type in parentheses.
136+
int objectTypeEnd = symbol.name.indexOf(' (');
137+
final objectType = objectTypeEnd > 0
138+
? symbol.name.substring(0, objectTypeEnd)
139+
: symbol.name;
140+
143141
switch (objectType) {
144142
// Used for entries in the non-clustered portion of the read-only data
145143
// section that don't correspond to a specific Dart object.
@@ -152,8 +150,101 @@ void checkElf(String filename, {bool isAssembled = false}) {
152150
case 'PcDescriptors':
153151
case 'CompressedStackMaps':
154152
break;
153+
// In assembly snapshots, we use local object symbols to initialize the
154+
// InstructionsSection header with the right offset to the BSS section.
155+
case '_kDartVmSnapshotBss':
156+
case '_kDartIsolateSnapshotBss':
157+
Expect.isTrue(isAssembled);
158+
break;
155159
default:
156-
Expect.fail('unexpected object type $objectType');
160+
Expect.fail('unexpected object type $objectType in "${symbol.name}"');
157161
}
158162
}
159163
}
164+
165+
void checkSymbols(List<Symbol>? snapshotSymbols, List<Symbol> debugInfoSymbols,
166+
{required bool isAssembled}) {
167+
// All symbols in the separate debugging info are created by the VM.
168+
Expect.isNotEmpty(debugInfoSymbols);
169+
checkVMSymbolsAreValid(debugInfoSymbols,
170+
source: 'debug info', isAssembled: isAssembled);
171+
if (snapshotSymbols == null) return;
172+
List<Symbol> checkedSnapshotSymbols = snapshotSymbols;
173+
if (isAssembled) {
174+
final names = debugInfoSymbols.map((s) => s.name).toSet();
175+
// All VM-generated symbols should have unique names in assembled output.
176+
Expect.equals(names.length, debugInfoSymbols.length);
177+
// For assembled snapshots, we may have symbols that are created by the
178+
// assembler and not the VM, so ignore those symbols. Since all VM symbols
179+
// have unique names when generating assembly, we just check that the
180+
// debug info has a symbol with the same name.
181+
checkedSnapshotSymbols = <Symbol>[];
182+
for (final symbol in snapshotSymbols) {
183+
if (names.contains(symbol.name)) {
184+
checkedSnapshotSymbols.add(symbol);
185+
}
186+
}
187+
}
188+
checkVMSymbolsAreValid(checkedSnapshotSymbols,
189+
source: 'snapshot', isAssembled: isAssembled);
190+
}
191+
192+
void checkElf(Elf? snapshot, Elf debugInfo, {required bool isAssembled}) {
193+
// All symbol tables have an initial entry with zero-valued fields.
194+
final snapshotDynamicSymbols = snapshot?.dynamicSymbols?.skip(1)?.toList();
195+
final debugDynamicSymbols = debugInfo.dynamicSymbols.skip(1).toList();
196+
final snapshotStaticSymbols = snapshot?.staticSymbols?.skip(1)?.toList();
197+
final debugStaticSymbols = debugInfo.staticSymbols.skip(1).toList();
198+
199+
// First, do our general round of checks against each group of tables.
200+
checkSymbols(snapshotDynamicSymbols, debugDynamicSymbols,
201+
isAssembled: isAssembled);
202+
checkSymbols(snapshotStaticSymbols, debugStaticSymbols,
203+
isAssembled: isAssembled);
204+
205+
// Now do some additional spot checks to make sure we actually haven't missed
206+
// generating some expected VM symbols by examining the debug info tables,
207+
// which only contain VM generated symbols.
208+
209+
// For the dynamic symbol tables, we expect that all VM symbols are global
210+
// object symbols.
211+
for (final symbol in debugDynamicSymbols) {
212+
Expect.equals(symbol.bind, SymbolBinding.STB_GLOBAL,
213+
'Expected all global symbols in the dynamic table, got $symbol');
214+
Expect.equals(symbol.type, SymbolType.STT_OBJECT,
215+
'Expected all object symbols in the dynamic table, got $symbol');
216+
}
217+
218+
final debugLocalSymbols =
219+
debugStaticSymbols.where((s) => s.bind == SymbolBinding.STB_LOCAL);
220+
final debugLocalObjectSymbols =
221+
debugLocalSymbols.where((s) => s.type == SymbolType.STT_OBJECT);
222+
// We should be generating at least _some_ local object symbols, since we're
223+
// using the --add-readonly-data-symbols flag.
224+
Expect.isNotEmpty(debugLocalObjectSymbols);
225+
226+
// We expect exactly two local object symbols with names starting with
227+
// 'RawBytes'.
228+
int rawBytesSeen = debugLocalObjectSymbols.fold<int>(
229+
0, (i, s) => i + (s.name.startsWith('RawBytes') ? 1 : 0));
230+
Expect.equals(2, rawBytesSeen,
231+
'saw $rawBytesSeen (!= 2) RawBytes local object symbols');
232+
233+
// All snapshots include at least one (and likely many) duplicate local
234+
// symbols. For assembly snapshots and their separate debugging information,
235+
// these symbols will have a numeric suffix to make them unique. In
236+
// direct-to-ELF snapshots and their separate debugging information, we allow
237+
// duplicate symbol names and thus there should be no numeric suffixes.
238+
bool sawUniqueSuffix = false;
239+
for (final symbol in debugLocalSymbols) {
240+
if (_uniqueSuffixRegexp.hasMatch(symbol.name)) {
241+
if (!isAssembled) {
242+
Expect.fail('Saw numeric suffix on symbol: $symbol');
243+
}
244+
sawUniqueSuffix = true;
245+
}
246+
}
247+
if (isAssembled) {
248+
Expect.isTrue(sawUniqueSuffix, 'No numeric suffixes seen');
249+
}
250+
}

0 commit comments

Comments
 (0)