Revert "[pkg/native_stack_traces] Support Mach-O dSYM debugging information."
This reverts commit 08c13f173c3715fd768d768566eeccf1f9f14c3b.
Reason for revert: Causing failures on simarm, simarm64, etc
Original change's description:
> [pkg/native_stack_traces] Support Mach-O dSYM debugging information.
>
> TEST=vm/dart{,_2}/use_dwarf_stack_traces_flag
>
> Bug: https://github.com/dart-lang/sdk/issues/43612
> Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-mac-product-x64-try,pkg-mac-release-arm64-try,vm-kernel-mac-release-arm64-try,vm-kernel-precomp-nnbd-mac-release-arm64-try
> Change-Id: Icda21bb14dcc0cf4784cea118e6ba7dd4edd35aa
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250381
> Commit-Queue: Tess Strickland <sstrickl@google.com>
> Reviewed-by: Slava Egorov <vegorov@google.com>
# Not skipping CQ checks because original CL landed > 1 day ago.
Bug: https://github.com/dart-lang/sdk/issues/43612
Change-Id: I020c29f7329e9b53a8fe0f4f4a4de4070fca0ec3
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-mac-product-x64-try,pkg-mac-release-arm64-try,vm-kernel-mac-release-arm64-try,vm-kernel-precomp-nnbd-mac-release-arm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251242
Reviewed-by: Ben Konyi <bkonyi@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index bba7560e..b96e965 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,9 +1,3 @@
-## 0.5.0
-
-- Add support for parsing DWARF in Mach-O files and dSYM directories.
-- Add `dump` command to replace the old `--dump_debug_file_contents`
- flag to `find` and `translate`.
-
## 0.4.6
- Upgrade to `package:lints` 2.0.
diff --git a/pkg/native_stack_traces/bin/decode.dart b/pkg/native_stack_traces/bin/decode.dart
index cb44a02..12c61ef 100644
--- a/pkg/native_stack_traces/bin/decode.dart
+++ b/pkg/native_stack_traces/bin/decode.dart
@@ -18,11 +18,10 @@
..addFlag('verbose',
abbr: 'v',
negatable: false,
- help: 'Translate all frames, not just user or library code frames');
-
-final ArgParser _dumpParser = ArgParser(allowTrailingOptions: true)
- ..addOption('output',
- abbr: 'o', help: 'Filename for generated output', valueHelp: 'FILE');
+ help: 'Translate all frames, not just user or library code frames')
+ ..addFlag('dump_debug_file_contents',
+ negatable: false,
+ help: 'Dump all the parsed information from the debugging file');
final ArgParser _translateParser =
_createBaseDebugParser(ArgParser(allowTrailingOptions: true))
@@ -49,7 +48,6 @@
final ArgParser _helpParser = ArgParser(allowTrailingOptions: true);
final ArgParser _argParser = ArgParser(allowTrailingOptions: true)
- ..addCommand('dump', _dumpParser)
..addCommand('help', _helpParser)
..addCommand('find', _findParser)
..addCommand('translate', _translateParser)
@@ -125,22 +123,12 @@
Options specific to the find command:
${_findParser.usage}''';
-final String _dumpUsage = '''
-Usage: decode dump [options] <snapshot>
-
-The dump command dumps the DWARF information in the given snapshot to either
-standard output or a given output file.
-
-Options specific to the dump command:
-${_dumpParser.usage}''';
-
final _usages = <String?, String>{
null: _mainUsage,
'': _mainUsage,
'help': _helpUsage,
'translate': _translateUsage,
'find': _findUsage,
- 'dump': _dumpUsage,
};
const int _badUsageExitCode = 1;
@@ -174,16 +162,15 @@
return null;
}
final filename = path.canonicalize(path.normalize(original));
- try {
- final dwarf = Dwarf.fromFile(filename);
- if (dwarf == null) {
- usageError('file "$original" does not contain debugging information');
- }
- return dwarf;
- } on io.FileSystemException {
+ if (!io.File(filename).existsSync()) {
usageError('debug file "$original" does not exist');
return null;
}
+ final dwarf = Dwarf.fromFile(filename);
+ if (dwarf == null) {
+ usageError('file "$original" does not contain debugging information');
+ }
+ return dwarf;
}
void find(ArgResults options) {
@@ -212,6 +199,10 @@
final dwarf = _loadFromFile(options['debug'], usageError);
if (dwarf == null) return;
+ if (options['dump_debug_file_contents']) {
+ print(dwarf.dumpFileInfo());
+ }
+
if ((options['vm_start'] == null) != (options['isolate_start'] == null)) {
return usageError('need both VM start and isolate start');
}
@@ -275,6 +266,9 @@
if (dwarf == null) {
return;
}
+ if (options['dump_debug_file_contents']) {
+ print(dwarf.dumpFileInfo());
+ }
final verbose = options['verbose'];
final output = options['output'] != null
@@ -297,27 +291,6 @@
await output.close();
}
-Future<void> dump(ArgResults options) async {
- void usageError(String message) => errorWithUsage(message, command: 'dump');
-
- if (options.rest.isEmpty) {
- return usageError('must provide a path to an ELF file or dSYM directory '
- 'that contains DWARF information');
- }
- final dwarf = _loadFromFile(options.rest.first, usageError);
- if (dwarf == null) {
- return usageError("'${options.rest.first}' contains no DWARF information");
- }
-
- final output = options['output'] != null
- ? io.File(path.canonicalize(path.normalize(options['output'])))
- .openWrite()
- : io.stdout;
- output.write(dwarf.dumpFileInfo());
- await output.flush();
- await output.close();
-}
-
Future<void> main(List<String> arguments) async {
ArgResults options;
@@ -337,7 +310,5 @@
return find(options.command!);
case 'translate':
return await translate(options.command!);
- case 'dump':
- return await dump(options.command!);
}
}
diff --git a/pkg/native_stack_traces/lib/src/convert.dart b/pkg/native_stack_traces/lib/src/convert.dart
index 34c17c3..0bc8f24 100644
--- a/pkg/native_stack_traces/lib/src/convert.dart
+++ b/pkg/native_stack_traces/lib/src/convert.dart
@@ -178,21 +178,18 @@
class DwarfStackTraceDecoder extends StreamTransformerBase<String, String> {
final Dwarf _dwarf;
final bool _includeInternalFrames;
- StackTraceHeader? _header;
DwarfStackTraceDecoder(this._dwarf, {bool includeInternalFrames = false})
: _includeInternalFrames = includeInternalFrames;
- PCOffset? offsetOf(int address) => _header?.offsetOf(address);
-
@override
Stream<String> bind(Stream<String> stream) async* {
var depth = 0;
- _header = null;
+ StackTraceHeader? header;
await for (final line in stream) {
final parsedHeader = _parseInstructionsLine(line);
if (parsedHeader != null) {
- _header = parsedHeader;
+ header = parsedHeader;
depth = 0;
yield line;
continue;
@@ -200,7 +197,7 @@
// If at any point we can't get appropriate information for the current
// line as a stack trace line, then just pass the line through unchanged.
final lineMatch = _traceLineRE.firstMatch(line);
- final offset = _retrievePCOffset(_header, lineMatch);
+ final offset = _retrievePCOffset(header, lineMatch);
final callInfo = offset?.callInfoFrom(_dwarf,
includeInternalFrames: _includeInternalFrames);
if (callInfo == null) {
diff --git a/pkg/native_stack_traces/lib/src/dwarf.dart b/pkg/native_stack_traces/lib/src/dwarf.dart
index 665f0c9..93a2af4 100644
--- a/pkg/native_stack_traces/lib/src/dwarf.dart
+++ b/pkg/native_stack_traces/lib/src/dwarf.dart
@@ -6,9 +6,8 @@
import 'dart:math';
import 'dart:typed_data';
-import 'dwarf_container.dart';
+import 'constants.dart' as constants;
import 'elf.dart';
-import 'macho.dart';
import 'reader.dart';
int _initialLengthValue(Reader reader) {
@@ -103,14 +102,12 @@
reference4,
sectionOffset,
string,
- strp,
}
const _attributeForms = <int, _AttributeForm>{
0x01: _AttributeForm.address,
0x08: _AttributeForm.string,
0x0c: _AttributeForm.flag,
- 0x0e: _AttributeForm.strp,
0x0f: _AttributeForm.constant,
0x13: _AttributeForm.reference4,
0x17: _AttributeForm.sectionOffset,
@@ -119,7 +116,6 @@
const _attributeFormStrings = <_AttributeForm, String>{
_AttributeForm.address: 'DW_FORM_addr',
_AttributeForm.string: 'DW_FORM_string',
- _AttributeForm.strp: 'DW_FORM_strp',
_AttributeForm.flag: 'DW_FORM_flag',
_AttributeForm.constant: 'DW_FORM_udata',
_AttributeForm.reference4: 'DW_FORM_ref4',
@@ -149,9 +145,6 @@
switch (form) {
case _AttributeForm.string:
return reader.readNullTerminatedString();
- case _AttributeForm.strp:
- final offset = reader.readBytes(4);
- return header.stringTable[offset]!;
case _AttributeForm.flag:
return reader.readByte() != 0;
case _AttributeForm.address:
@@ -168,7 +161,6 @@
String valueToString(Object value, [CompilationUnit? unit]) {
switch (form) {
case _AttributeForm.string:
- case _AttributeForm.strp:
return value as String;
case _AttributeForm.flag:
return value.toString();
@@ -439,16 +431,14 @@
final int addressSize;
// ignore: library_private_types_in_public_api
final _AbbreviationsTable abbreviations;
- final DwarfContainerStringTable stringTable;
CompilationUnitHeader._(this.size, this.version, this.abbreviationsOffset,
- this.addressSize, this.abbreviations, this.stringTable);
+ this.addressSize, this.abbreviations);
static CompilationUnitHeader? fromReader(
Reader reader,
// ignore: library_private_types_in_public_api
- Map<int, _AbbreviationsTable> abbreviationsTables,
- DwarfContainerStringTable stringTable) {
+ Map<int, _AbbreviationsTable> abbreviationsTables) {
final size = _initialLengthValue(reader);
// An empty unit is an ending marker.
if (size == 0) return null;
@@ -463,8 +453,8 @@
'0x${paddedHex(abbreviationsOffset, 4)}');
}
final addressSize = reader.readByte();
- return CompilationUnitHeader._(size, version, abbreviationsOffset,
- addressSize, abbreviationsTable, stringTable);
+ return CompilationUnitHeader._(
+ size, version, abbreviationsOffset, addressSize, abbreviationsTable);
}
void writeToStringBuffer(StringBuffer buffer) {
@@ -499,10 +489,9 @@
static CompilationUnit? fromReader(
Reader reader,
// ignore: library_private_types_in_public_api
- Map<int, _AbbreviationsTable> abbreviationsTables,
- DwarfContainerStringTable stringTable) {
- final header = CompilationUnitHeader.fromReader(
- reader, abbreviationsTables, stringTable);
+ Map<int, _AbbreviationsTable> abbreviationsTables) {
+ final header =
+ CompilationUnitHeader.fromReader(reader, abbreviationsTables);
if (header == null) return null;
final referenceTable = Map.fromEntries(reader.readRepeatedWithOffsets(
@@ -574,11 +563,10 @@
static DebugInfo fromReader(
Reader reader,
// ignore: library_private_types_in_public_api
- Map<int, _AbbreviationsTable> abbreviationsTable,
- DwarfContainerStringTable stringTable) {
+ Map<int, _AbbreviationsTable> abbreviationsTable) {
final units = reader
- .readRepeated((r) =>
- CompilationUnit.fromReader(reader, abbreviationsTable, stringTable))
+ .readRepeated(
+ (r) => CompilationUnit.fromReader(reader, abbreviationsTable))
.toList();
return DebugInfo._(units);
}
@@ -926,18 +914,14 @@
void applySpecialOpcode(int opcode) {
final adjustedOpcode = opcode - header.opcodeBase;
- final addrDiff = (adjustedOpcode ~/ header.lineRange) *
- header.minimumInstructionLength;
- final lineDiff = header.lineBase + (adjustedOpcode % header.lineRange);
- state.address += addrDiff;
- state.line += lineDiff;
+ state.address = adjustedOpcode ~/ header.lineRange;
+ state.line += header.lineBase + (adjustedOpcode % header.lineRange);
}
while (!reader.done) {
final opcode = reader.readByte();
if (opcode >= header.opcodeBase) {
applySpecialOpcode(opcode);
- yield state.clone();
continue;
}
switch (opcode) {
@@ -991,8 +975,7 @@
state.basicBlock = true;
break;
case 8: // DW_LNS_const_add_pc
- state.address += ((255 - header.opcodeBase) ~/ header.lineRange) *
- header.minimumInstructionLength;
+ applySpecialOpcode(255);
break;
case 9: // DW_LNS_fixed_advance_pc
state.address += reader.readBytes(2);
@@ -1217,19 +1200,12 @@
other is PCOffset && offset == other.offset && section == other.section;
@override
- String toString() => 'PCOffset($section, 0x${offset.toRadixString(16)})';
-}
-
-class UnimplementedStringTable extends DwarfContainerStringTable {
- @override
- String? operator [](int index) {
- throw 'No string table found in DWARF information';
- }
+ String toString() => 'PCOffset($section, $offset)';
}
/// The DWARF debugging information for a Dart snapshot.
class Dwarf {
- final DwarfContainer _container;
+ final Elf _elf;
final Map<int, _AbbreviationsTable> _abbreviationsTables;
final DebugInfo _debugInfo;
final LineNumberInfo _lineNumberInfo;
@@ -1242,38 +1218,17 @@
/// DWARF information.
final int isolateStartAddress;
- Dwarf._(this._container, this._abbreviationsTables, this._debugInfo,
+ Dwarf._(this._elf, this._abbreviationsTables, this._debugInfo,
this._lineNumberInfo, this.vmStartAddress, this.isolateStartAddress);
- static Dwarf fromDwarfContainer(Reader reader, DwarfContainer container) {
- final abbrevReader = container.abbreviationsTableReader(reader);
- final abbreviationsTables = Map.fromEntries(
- abbrevReader.readRepeatedWithOffsets(_AbbreviationsTable.fromReader));
-
- final lineNumberInfo =
- LineNumberInfo.fromReader(container.lineNumberInfoReader(reader));
-
- final stringTable = container.stringTable ?? UnimplementedStringTable();
- final debugInfo = DebugInfo.fromReader(
- container.debugInfoReader(reader), abbreviationsTables, stringTable);
-
- return Dwarf._(container, abbreviationsTables, debugInfo, lineNumberInfo,
- container.vmStartAddress, container.isolateStartAddress);
- }
-
/// Attempts to load the DWARF debugging information from the reader.
///
/// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
static Dwarf? fromReader(Reader reader) {
+ // Currently, the only DWARF-containing format we recognize is ELF.
final elf = Elf.fromReader(reader);
- if (elf != null) {
- return Dwarf.fromDwarfContainer(reader, elf);
- }
- final macho = MachO.fromReader(reader);
- if (macho != null) {
- return Dwarf.fromDwarfContainer(reader, macho);
- }
- return null;
+ if (elf == null) return null;
+ return Dwarf._loadSectionsFromElf(reader, elf);
}
/// Attempts to load the DWARF debugging information from the given bytes.
@@ -1286,12 +1241,54 @@
///
/// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
static Dwarf? fromFile(String path) =>
- Dwarf.fromReader(Reader.fromFile(MachO.handleDSYM(path)));
+ Dwarf.fromReader(Reader.fromFile(path));
+
+ static Dwarf _loadSectionsFromElf(Reader reader, Elf elf) {
+ final abbrevSection = elf.namedSections('.debug_abbrev').single;
+ final abbrevReader = abbrevSection.refocusedCopy(reader);
+ final abbreviationsTables = Map.fromEntries(
+ abbrevReader.readRepeatedWithOffsets(_AbbreviationsTable.fromReader));
+
+ final lineNumberSection = elf.namedSections('.debug_line').single;
+ final lineNumberInfo =
+ LineNumberInfo.fromReader(lineNumberSection.refocusedCopy(reader));
+
+ final infoSection = elf.namedSections('.debug_info').single;
+ final debugInfo = DebugInfo.fromReader(
+ infoSection.refocusedCopy(reader), abbreviationsTables);
+
+ final vmStartSymbol = elf.dynamicSymbolFor(constants.vmSymbolName);
+ if (vmStartSymbol == null) {
+ throw FormatException(
+ 'Expected a dynamic symbol with name ${constants.vmSymbolName}');
+ }
+ final vmStartAddress = vmStartSymbol.value;
+
+ final isolateStartSymbol =
+ elf.dynamicSymbolFor(constants.isolateSymbolName);
+ if (isolateStartSymbol == null) {
+ throw FormatException(
+ 'Expected a dynamic symbol with name ${constants.isolateSymbolName}');
+ }
+ final isolateStartAddress = isolateStartSymbol.value;
+
+ return Dwarf._(elf, abbreviationsTables, debugInfo, lineNumberInfo,
+ vmStartAddress, isolateStartAddress);
+ }
/// The build ID for the debugging information.
///
/// Returns null if there is no build ID information recorded.
- String? get buildId => _container.buildId;
+ String? get buildId {
+ final sections = _elf.namedSections(constants.buildIdSectionName);
+ if (sections.isEmpty) return null;
+ final note = sections.single as Note;
+ if (note.type != constants.buildIdNoteType) return null;
+ if (note.name != constants.buildIdNoteName) return null;
+ return note.description
+ .map((i) => i.toRadixString(16).padLeft(2, '0'))
+ .join();
+ }
/// The call information for the given virtual address. There may be
/// multiple [CallInfo] objects returned for a single virtual address when
@@ -1305,7 +1302,7 @@
{bool includeInternalFrames = false}) {
var calls = _debugInfo.callInfo(_lineNumberInfo, address);
if (calls == null) {
- final symbol = _container.staticSymbolAt(address);
+ final symbol = _elf.staticSymbolAt(address);
if (symbol != null) {
final offset = address - symbol.value;
calls = <CallInfo>[StubCallInfo(name: symbol.name, offset: offset)];
@@ -1361,7 +1358,7 @@
String dumpFileInfo() {
final buffer = StringBuffer();
- _container.writeToStringBuffer(buffer);
+ _elf.writeToStringBuffer(buffer);
buffer.writeln();
writeToStringBuffer(buffer);
return buffer.toString();
diff --git a/pkg/native_stack_traces/lib/src/dwarf_container.dart b/pkg/native_stack_traces/lib/src/dwarf_container.dart
deleted file mode 100644
index feb3b57..0000000
--- a/pkg/native_stack_traces/lib/src/dwarf_container.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'reader.dart';
-
-abstract class DwarfContainerStringTable {
- String? operator [](int index);
-}
-
-abstract class DwarfContainerSymbol {
- int get value;
- String get name;
-}
-
-abstract class DwarfContainer {
- Reader debugInfoReader(Reader containerReader);
- Reader lineNumberInfoReader(Reader containerReader);
- Reader abbreviationsTableReader(Reader containerReader);
- DwarfContainerSymbol? staticSymbolAt(int address);
-
- int get vmStartAddress;
- int get isolateStartAddress;
-
- String? get buildId;
-
- DwarfContainerStringTable? get stringTable;
-
- void writeToStringBuffer(StringBuffer buffer);
-}
diff --git a/pkg/native_stack_traces/lib/src/elf.dart b/pkg/native_stack_traces/lib/src/elf.dart
index 4d69efc..c29b1e4 100644
--- a/pkg/native_stack_traces/lib/src/elf.dart
+++ b/pkg/native_stack_traces/lib/src/elf.dart
@@ -6,8 +6,6 @@
import 'dart:typed_data';
-import 'constants.dart' as constants;
-import 'dwarf_container.dart';
import 'reader.dart';
int _readElfBytes(Reader reader, int bytes, int alignment) {
@@ -92,12 +90,10 @@
this.sectionHeaderStringsIndex);
static ElfHeader? fromReader(Reader reader) {
- final start = reader.offset;
final fileSize = reader.length;
for (final sigByte in _ELFMAG.codeUnits) {
if (reader.readByte() != sigByte) {
- reader.seek(start, absolute: true);
return null;
}
}
@@ -270,11 +266,7 @@
static const _PT_NULL = 0;
static const _PT_LOAD = 1;
static const _PT_DYNAMIC = 2;
- static const _PT_NOTE = 4;
static const _PT_PHDR = 6;
- static const _PT_GNU_EH_FRAME = 0x6474e550;
- static const _PT_GNU_STACK = 0x6474e551;
- static const _PT_GNU_RELRO = 0x6474e552;
ProgramHeaderEntry._(this.type, this.flags, this.offset, this.vaddr,
this.paddr, this.filesz, this.memsz, this.align, this.wordSize);
@@ -304,11 +296,7 @@
_PT_NULL: 'PT_NULL',
_PT_LOAD: 'PT_LOAD',
_PT_DYNAMIC: 'PT_DYNAMIC',
- _PT_NOTE: 'PT_NOTE',
_PT_PHDR: 'PT_PHDR',
- _PT_GNU_EH_FRAME: 'PT_GNU_EH_FRAME',
- _PT_GNU_STACK: 'PT_GNU_STACK',
- _PT_GNU_RELRO: 'PT_GNU_RELRO',
};
static String _typeToString(int type) =>
@@ -658,7 +646,7 @@
}
/// A map from table offsets to strings, used to store names of ELF objects.
-class StringTable extends Section implements DwarfContainerStringTable {
+class StringTable extends Section {
final Map<int, String> _entries;
StringTable._(entry, this._entries) : super._(entry);
@@ -670,22 +658,8 @@
return StringTable._(entry, entries);
}
- @override
- String? operator [](int index) {
- // Fast case: Index is for the start of a null terminated string.
- if (_entries.containsKey(index)) {
- return _entries[index];
- }
- // We can index into null terminated string entries for suffixes of
- // that string, so do a linear search to find the appropriate entry.
- for (final kv in _entries.entries) {
- final start = index - kv.key;
- if (start >= 0 && start <= kv.value.length) {
- return kv.value.substring(start);
- }
- }
- return null;
- }
+ String? operator [](int index) => _entries[index];
+ bool containsKey(int index) => _entries.containsKey(index);
@override
void writeToStringBuffer(StringBuffer buffer) {
@@ -706,7 +680,6 @@
enum SymbolBinding {
STB_LOCAL,
STB_GLOBAL,
- STB_WEAK,
}
enum SymbolType {
@@ -723,17 +696,15 @@
}
/// A symbol in an ELF file, which names a portion of the virtual address space.
-class Symbol implements DwarfContainerSymbol {
+class Symbol {
final int nameIndex;
final int info;
final int other;
final int sectionIndex;
- @override
final int value;
final int size;
final int _wordSize;
- @override
- late final String name;
+ late String name;
Symbol._(this.nameIndex, this.info, this.other, this.sectionIndex, this.value,
this.size, this._wordSize);
@@ -760,6 +731,14 @@
nameIndex, info, other, sectionIndex, value, size, wordSize);
}
+ void _cacheNameFromStringTable(StringTable table) {
+ final nameFromTable = table[nameIndex];
+ if (nameFromTable == null) {
+ throw FormatException('Index $nameIndex not found in string table');
+ }
+ name = nameFromTable;
+ }
+
SymbolBinding get bind => SymbolBinding.values[info >> 4];
SymbolType get type => SymbolType.values[info & 0x0f];
SymbolVisibility get visibility => SymbolVisibility.values[other & 0x03];
@@ -776,9 +755,6 @@
case SymbolBinding.STB_LOCAL:
buffer.write(' a local');
break;
- case SymbolBinding.STB_WEAK:
- buffer.write(' a weak');
- break;
}
switch (visibility) {
case SymbolVisibility.STV_DEFAULT:
@@ -828,13 +804,8 @@
void _cacheNames(StringTable stringTable) {
_nameCache.clear();
for (final symbol in _entries) {
- final index = symbol.nameIndex;
- final name = stringTable[index];
- if (name == null) {
- throw FormatException('Index $index not found in string table');
- }
- symbol.name = name;
- _nameCache[name] = symbol;
+ symbol._cacheNameFromStringTable(stringTable);
+ _nameCache[symbol.name] = symbol;
}
}
@@ -961,7 +932,7 @@
}
/// Information parsed from an Executable and Linking Format (ELF) file.
-class Elf implements DwarfContainer {
+class Elf {
final ElfHeader _header;
final ProgramHeader _programHeader;
final SectionHeader _sectionHeader;
@@ -1013,24 +984,16 @@
/// Reverse lookup of the static symbol that contains the given virtual
/// address. Returns null if no static symbol matching the address is found.
- @override
Symbol? staticSymbolAt(int address) {
- Symbol? bestSym;
for (final section in namedSections('.symtab')) {
final table = section as SymbolTable;
for (final symbol in table.values) {
final start = symbol.value;
- if (start > address) continue;
- // If given a non-zero extent of a symbol, make sure the address is
- // within the extent.
- if (symbol.size > 0 && (start + symbol.size <= address)) continue;
- // Pick the symbol with a start closest to the given address.
- if (bestSym == null || (bestSym.value < start)) {
- bestSym = symbol;
- }
+ final end = start + symbol.size;
+ if (start <= address && address < end) return symbol;
}
}
- return bestSym;
+ return null;
}
/// Creates an [Elf] from the data pointed to by [reader].
@@ -1114,55 +1077,6 @@
header, programHeader, sectionHeader, sections, sectionsByName);
}
- @override
- Reader abbreviationsTableReader(Reader containerReader) =>
- namedSections('.debug_abbrev').single.refocusedCopy(containerReader);
-
- @override
- Reader lineNumberInfoReader(Reader containerReader) =>
- namedSections('.debug_line').single.refocusedCopy(containerReader);
-
- @override
- Reader debugInfoReader(Reader containerReader) =>
- namedSections('.debug_info').single.refocusedCopy(containerReader);
-
- @override
- int get vmStartAddress {
- final vmStartSymbol = dynamicSymbolFor(constants.vmSymbolName);
- if (vmStartSymbol == null) {
- throw FormatException(
- 'Expected a dynamic symbol with name ${constants.vmSymbolName}');
- }
- return vmStartSymbol.value;
- }
-
- @override
- int get isolateStartAddress {
- final isolateStartSymbol = dynamicSymbolFor(constants.isolateSymbolName);
- if (isolateStartSymbol == null) {
- throw FormatException(
- 'Expected a dynamic symbol with name ${constants.isolateSymbolName}');
- }
- return isolateStartSymbol.value;
- }
-
- @override
- String? get buildId {
- final sections = namedSections(constants.buildIdSectionName);
- if (sections.isEmpty) return null;
- final note = sections.single as Note;
- if (note.type != constants.buildIdNoteType) return null;
- if (note.name != constants.buildIdNoteName) return null;
- return note.description
- .map((i) => i.toRadixString(16).padLeft(2, '0'))
- .join();
- }
-
- // Currently we don't handle DWARF uses of string tables in ELF files.
- @override
- DwarfContainerStringTable? get stringTable => null;
-
- @override
void writeToStringBuffer(StringBuffer buffer) {
buffer
..writeln('-----------------------------------------------------')
diff --git a/pkg/native_stack_traces/lib/src/macho.dart b/pkg/native_stack_traces/lib/src/macho.dart
deleted file mode 100644
index d46a507..0000000
--- a/pkg/native_stack_traces/lib/src/macho.dart
+++ /dev/null
@@ -1,548 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// ignore_for_file: constant_identifier_names
-
-import 'dart:typed_data';
-
-import 'package:path/path.dart' as path;
-
-import 'constants.dart' as constants;
-import 'dwarf_container.dart';
-import 'reader.dart';
-
-int _readMachOUint8(Reader reader) => reader.readByte(signed: false);
-
-int _readMachOUint16(Reader reader) => reader.readBytes(2, signed: false);
-
-int _readMachOUint32(Reader reader) => reader.readBytes(4, signed: false);
-
-int _readMachOUword(Reader reader) =>
- reader.readBytes(reader.wordSize, signed: false);
-
-class StringTable implements DwarfContainerStringTable {
- final Map<int, String> _stringsByOffset;
-
- StringTable._(this._stringsByOffset);
-
- static StringTable fromReader(Reader reader) => StringTable._(Map.fromEntries(
- reader.readRepeatedWithOffsets((r) => r.readNullTerminatedString())));
-
- @override
- String? operator [](int index) {
- // Fast case: Index is for the start of a null terminated string.
- if (_stringsByOffset.containsKey(index)) {
- return _stringsByOffset[index];
- }
- // We can index into null terminated string entries for suffixes of
- // that string, so do a linear search to find the appropriate entry.
- for (final kv in _stringsByOffset.entries) {
- final start = index - kv.key;
- if (start >= 0 && start <= kv.value.length) {
- return kv.value.substring(start);
- }
- }
- return null;
- }
-
- void writeToStringBuffer(StringBuffer buffer) {
- for (final k in _stringsByOffset.keys) {
- buffer
- ..write(k.toString().padLeft(8, ' '))
- ..write(' => ')
- ..writeln(_stringsByOffset[k]);
- }
- }
-
- @override
- String toString() {
- final buffer = StringBuffer();
- writeToStringBuffer(buffer);
- return buffer.toString();
- }
-}
-
-class Symbol implements DwarfContainerSymbol {
- final int index;
- final int type;
- final int sect;
- final int desc;
- @override
- final int value;
- @override
- late final String name;
-
- Symbol._(this.index, this.type, this.sect, this.desc, this.value);
-
- static Symbol fromReader(Reader reader) {
- final index = _readMachOUint32(reader);
- final type = _readMachOUint8(reader);
- final sect = _readMachOUint8(reader);
- final desc = _readMachOUint16(reader);
- final value = _readMachOUword(reader);
- return Symbol._(index, type, sect, desc, value);
- }
-}
-
-class SymbolTable {
- final Map<String, Symbol> _symbols;
-
- SymbolTable._(this._symbols);
-
- static SymbolTable fromReader(
- Reader reader, int nsyms, StringTable stringTable) {
- final symbols = <String, Symbol>{};
- for (int i = 0; i < nsyms; i++) {
- final symbol = Symbol.fromReader(reader);
- final index = symbol.index;
- final name = stringTable[index];
- if (name == null) {
- throw FormatException('Index $index not found in string table');
- }
- symbol.name = name;
- symbols[name] = symbol;
- }
- return SymbolTable._(symbols);
- }
-
- Iterable<String> get keys => _symbols.keys;
- Iterable<Symbol> get values => _symbols.values;
-
- Symbol? operator [](String name) => _symbols[name];
-
- bool containsKey(String name) => _symbols.containsKey(name);
-}
-
-class LoadCommand {
- final int cmd;
- final int cmdsize;
-
- LoadCommand._(this.cmd, this.cmdsize);
-
- static const LC_SEGMENT = 0x1;
- static const LC_SYMTAB = 0x2;
- static const LC_SEGMENT_64 = 0x19;
-
- static LoadCommand fromReader(Reader reader) {
- final start = reader.offset; // cmdsize includes size of cmd and cmdsize.
- final cmd = _readMachOUint32(reader);
- final cmdsize = _readMachOUint32(reader);
- LoadCommand command = LoadCommand._(cmd, cmdsize);
- switch (cmd) {
- case LC_SEGMENT:
- case LC_SEGMENT_64:
- command = SegmentCommand.fromReader(reader, cmd, cmdsize);
- break;
- case LC_SYMTAB:
- command = SymbolTableCommand.fromReader(reader, cmd, cmdsize);
- break;
- default:
- break;
- }
- reader.seek(start + cmdsize, absolute: true);
- return command;
- }
-
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..write('Uninterpreted command 0x')
- ..write(cmd.toRadixString(16))
- ..write(' of size ')
- ..writeln(cmdsize);
- }
-
- @override
- String toString() {
- StringBuffer buffer = StringBuffer();
- writeToStringBuffer(buffer);
- return buffer.toString();
- }
-}
-
-class SegmentCommand extends LoadCommand {
- final String segname;
- final int vmaddr;
- final int vmsize;
- final int fileoff;
- final int filesize;
- final int maxprot;
- final int initprot;
- final int nsects;
- final int flags;
- final Map<String, Section> sections;
-
- SegmentCommand._(
- int cmd,
- int cmdsize,
- this.segname,
- this.vmaddr,
- this.vmsize,
- this.fileoff,
- this.filesize,
- this.maxprot,
- this.initprot,
- this.nsects,
- this.flags,
- this.sections)
- : super._(cmd, cmdsize);
-
- static SegmentCommand fromReader(Reader reader, int cmd, int cmdsize) {
- final segname = reader.readFixedLengthNullTerminatedString(16);
- final vmaddr = _readMachOUword(reader);
- final vmsize = _readMachOUword(reader);
- final fileoff = _readMachOUword(reader);
- final filesize = _readMachOUword(reader);
- final maxprot = _readMachOUint32(reader);
- final initprot = _readMachOUint32(reader);
- final nsects = _readMachOUint32(reader);
- final flags = _readMachOUint32(reader);
- final sections = <String, Section>{};
- for (int i = 0; i < nsects; i++) {
- final section = Section.fromReader(reader);
- sections[section.sectname] = section;
- }
- return SegmentCommand._(cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
- filesize, maxprot, initprot, nsects, flags, sections);
- }
-
- @override
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..write('Segment "')
- ..write(segname)
- ..write('" of size ')
- ..write(filesize)
- ..write(' at offset 0x')
- ..writeln(fileoff.toRadixString(16));
- buffer.writeln('Sections:');
- for (final section in sections.values) {
- section.writeToStringBuffer(buffer);
- buffer.writeln();
- }
- }
-}
-
-class Section {
- String sectname;
- String segname;
- int addr;
- int size;
- int offset;
- int align;
- int reloff;
- int nreloc;
- int flags;
- int reserved1;
- int reserved2;
- int? reserved3;
-
- Section._(
- this.sectname,
- this.segname,
- this.addr,
- this.size,
- this.offset,
- this.align,
- this.reloff,
- this.nreloc,
- this.flags,
- this.reserved1,
- this.reserved2,
- this.reserved3);
-
- static Section fromReader(Reader reader) {
- final sectname = reader.readFixedLengthNullTerminatedString(16);
- final segname = reader.readFixedLengthNullTerminatedString(16);
- final addr = _readMachOUword(reader);
- final size = _readMachOUword(reader);
- final offset = _readMachOUint32(reader);
- final align = _readMachOUint32(reader);
- final reloff = _readMachOUint32(reader);
- final nreloc = _readMachOUint32(reader);
- final flags = _readMachOUint32(reader);
- final reserved1 = _readMachOUint32(reader);
- final reserved2 = _readMachOUint32(reader);
- final reserved3 = (reader.wordSize == 8) ? _readMachOUint32(reader) : null;
- return Section._(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2, reserved3);
- }
-
- Reader refocus(Reader reader) => reader.refocusedCopy(offset, size);
-
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..write('Section "')
- ..write(sectname)
- ..write('" of size ')
- ..write(size)
- ..write(' at offset 0x')
- ..write(paddedHex(offset, 4));
- }
-
- @override
- String toString() {
- StringBuffer buffer = StringBuffer();
- writeToStringBuffer(buffer);
- return buffer.toString();
- }
-}
-
-class SymbolTableCommand extends LoadCommand {
- final int _symoff;
- final int _nsyms;
- final int _stroff;
- final int _strsize;
-
- SymbolTableCommand._(int cmd, int cmdsize, this._symoff, this._nsyms,
- this._stroff, this._strsize)
- : super._(cmd, cmdsize);
-
- static SymbolTableCommand fromReader(Reader reader, int cmd, int cmdsize) {
- final symoff = _readMachOUint32(reader);
- final nsyms = _readMachOUint32(reader);
- final stroff = _readMachOUint32(reader);
- final strsize = _readMachOUint32(reader);
- return SymbolTableCommand._(cmd, cmdsize, symoff, nsyms, stroff, strsize);
- }
-
- SymbolTable load(Reader reader) {
- final stringTable =
- StringTable.fromReader(reader.refocusedCopy(_stroff, _strsize));
- return SymbolTable.fromReader(
- reader.refocusedCopy(_symoff), _nsyms, stringTable);
- }
-
- @override
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..write('Symbol table with ')
- ..write(_nsyms)
- ..write(' symbols of size ')
- ..writeln(cmdsize);
- }
-}
-
-class MachOHeader {
- final int magic;
- final int cputype;
- final int cpusubtype;
- final int filetype;
- final int ncmds;
- final int sizeofcmds;
- final int flags;
- final int? reserved;
- final int size;
-
- MachOHeader._(this.magic, this.cputype, this.cpusubtype, this.filetype,
- this.ncmds, this.sizeofcmds, this.flags, this.reserved, this.size);
-
- static const _MH_MAGIC = 0xfeedface;
- static const _MH_CIGAM = 0xcefaedfe;
- static const _MH_MAGIC_64 = 0xfeedfacf;
- static const _MH_CIGAM_64 = 0xcffaedfe;
-
- static MachOHeader? fromReader(Reader reader) {
- final start = reader.offset;
- // Initially assume host endianness.
- reader.endian = Endian.host;
- final magic = _readMachOUint32(reader);
- if (magic == _MH_MAGIC || magic == _MH_CIGAM) {
- reader.wordSize = 4;
- } else if (magic == _MH_MAGIC_64 || magic == _MH_CIGAM_64) {
- reader.wordSize = 8;
- } else {
- // Not an expected magic value, so not a supported Mach-O file.
- return null;
- }
- if (magic == _MH_CIGAM || magic == _MH_CIGAM_64) {
- reader.endian = Endian.host == Endian.big ? Endian.little : Endian.big;
- }
- final cputype = _readMachOUint32(reader);
- final cpusubtype = _readMachOUint32(reader);
- final filetype = _readMachOUint32(reader);
- final ncmds = _readMachOUint32(reader);
- final sizeofcmds = _readMachOUint32(reader);
- final flags = _readMachOUint32(reader);
- final reserved = reader.wordSize == 8 ? _readMachOUint32(reader) : null;
- final size = reader.offset - start;
- return MachOHeader._(magic, cputype, cpusubtype, filetype, ncmds,
- sizeofcmds, flags, reserved, size);
- }
-
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..write('Magic: 0x')
- ..writeln(paddedHex(magic, 4));
- buffer
- ..write('Cpu Type: 0x')
- ..writeln(paddedHex(cputype, 4));
- buffer
- ..write('Cpu Subtype: 0x')
- ..writeln(paddedHex(cpusubtype, 4));
- buffer
- ..write('Filetype: 0x')
- ..writeln(paddedHex(filetype, 4));
- buffer
- ..write('Number of commands: ')
- ..writeln(ncmds);
- buffer
- ..write('Size of commands: ')
- ..writeln(sizeofcmds);
- buffer
- ..write('Flags: 0x')
- ..writeln(paddedHex(flags, 4));
- if (reserved != null) {
- buffer
- ..write('Reserved: 0x')
- ..writeln(paddedHex(reserved!, 4));
- }
- }
-
- @override
- String toString() {
- final buffer = StringBuffer();
- writeToStringBuffer(buffer);
- return buffer.toString();
- }
-}
-
-class MachO implements DwarfContainer {
- final MachOHeader _header;
- final List<LoadCommand> _commands;
- final SymbolTable _symbolTable;
- final SegmentCommand _dwarfSegment;
- final StringTable? _dwarfStringTable;
-
- MachO._(this._header, this._commands, this._symbolTable, this._dwarfSegment,
- this._dwarfStringTable);
-
- static MachO? fromReader(Reader machOReader) {
- // MachO files contain absolute offsets from the start of the file, so
- // make sure we have a reader that a) makes no assumptions about the
- // endianness or word size, since we'll read those in the header and b)
- // has an internal offset of 0 so absolute offsets can be used directly.
- final reader = Reader.fromTypedData(ByteData.sublistView(machOReader.bdata,
- machOReader.bdata.offsetInBytes + machOReader.offset));
- final header = MachOHeader.fromReader(reader);
- if (header == null) return null;
-
- final commandReader =
- reader.refocusedCopy(reader.offset, header.sizeofcmds);
- final commands =
- List.of(commandReader.readRepeated(LoadCommand.fromReader));
- assert(commands.length == header.ncmds);
-
- final symbolTable =
- commands.whereType<SymbolTableCommand>().single.load(reader);
-
- final dwarfSegment = commands
- .whereType<SegmentCommand?>()
- .firstWhere((sc) => sc!.segname == '__DWARF', orElse: () => null);
- if (dwarfSegment == null) {
- print("No DWARF information in Mach-O file");
- return null;
- }
-
- final dwarfStringTableSection = dwarfSegment.sections['__debug_str'];
- StringTable? dwarfStringTable;
- if (dwarfStringTableSection != null) {
- dwarfStringTable =
- StringTable.fromReader(dwarfStringTableSection.refocus(reader));
- }
-
- // Set the wordSize and endian of the original reader before returning.
- machOReader.wordSize = reader.wordSize;
- machOReader.endian = reader.endian;
-
- return MachO._(
- header, commands, symbolTable, dwarfSegment, dwarfStringTable);
- }
-
- static String handleDSYM(String fileName) {
- if (!fileName.endsWith('.dSYM')) {
- return fileName;
- }
- var baseName = path.basename(fileName);
- baseName = baseName.substring(0, baseName.length - '.dSYM'.length);
- return path.join(fileName, 'Contents', 'Resources', 'DWARF', baseName);
- }
-
- static MachO? fromFile(String fileName) =>
- MachO.fromReader(Reader.fromFile(MachO.handleDSYM(fileName)));
-
- @override
- Reader abbreviationsTableReader(Reader reader) =>
- _dwarfSegment.sections['__debug_abbrev']!.refocus(reader);
- @override
- Reader lineNumberInfoReader(Reader reader) =>
- _dwarfSegment.sections['__debug_line']!.refocus(reader);
- @override
- Reader debugInfoReader(Reader reader) =>
- _dwarfSegment.sections['__debug_info']!.refocus(reader);
-
- @override
- int get vmStartAddress {
- if (!_symbolTable.containsKey(constants.vmSymbolName)) {
- throw FormatException(
- 'Expected a dynamic symbol with name ${constants.vmSymbolName}');
- }
- return _symbolTable[constants.vmSymbolName]!.value;
- }
-
- @override
- int get isolateStartAddress {
- if (!_symbolTable.containsKey(constants.isolateSymbolName)) {
- throw FormatException(
- 'Expected a dynamic symbol with name ${constants.isolateSymbolName}');
- }
- return _symbolTable[constants.isolateSymbolName]!.value;
- }
-
- @override
- String? get buildId => null;
-
- @override
- DwarfContainerStringTable? get stringTable => _dwarfStringTable;
-
- @override
- Symbol? staticSymbolAt(int address) {
- Symbol? bestSym;
- for (final symbol in _symbolTable.values) {
- if (symbol.value > address) continue;
- // Pick the symbol with a value closest to the given address.
- if (bestSym == null || (bestSym.value < symbol.value)) {
- bestSym = symbol;
- }
- }
- return bestSym;
- }
-
- @override
- void writeToStringBuffer(StringBuffer buffer) {
- buffer
- ..writeln('----------------------------------------')
- ..writeln(' Header')
- ..writeln('----------------------------------------')
- ..writeln('');
- _header.writeToStringBuffer(buffer);
- buffer
- ..writeln('')
- ..writeln('')
- ..writeln('----------------------------------------')
- ..writeln(' Load commands')
- ..writeln('----------------------------------------')
- ..writeln('');
- for (final command in _commands) {
- command.writeToStringBuffer(buffer);
- buffer.writeln('');
- }
- }
-
- @override
- String toString() {
- final buffer = StringBuffer();
- writeToStringBuffer(buffer);
- return buffer.toString();
- }
-}
diff --git a/pkg/native_stack_traces/lib/src/reader.dart b/pkg/native_stack_traces/lib/src/reader.dart
index 99148d3..8158878 100644
--- a/pkg/native_stack_traces/lib/src/reader.dart
+++ b/pkg/native_stack_traces/lib/src/reader.dart
@@ -37,15 +37,9 @@
bdata = ByteData.sublistView(File(path).readAsBytesSync());
/// Returns a reader focused on a different portion of the underlying buffer.
- /// If size is not provided, then the new reader extends to the end of the
- /// buffer.
- Reader refocusedCopy(int pos, [int? size]) {
+ Reader refocusedCopy(int pos, int size) {
assert(pos >= 0 && pos < bdata.buffer.lengthInBytes);
- if (size != null) {
- assert(size >= 0 && (pos + size) <= bdata.buffer.lengthInBytes);
- } else {
- size = bdata.buffer.lengthInBytes - pos;
- }
+ assert(size >= 0 && (pos + size) <= bdata.buffer.lengthInBytes);
return Reader.fromTypedData(ByteData.view(bdata.buffer, pos, size),
wordSize: _wordSize, endian: _endian);
}
@@ -57,7 +51,7 @@
void seek(int offset, {bool absolute = false}) {
final newOffset = (absolute ? 0 : _offset) + offset;
- assert(newOffset >= 0 && newOffset <= bdata.lengthInBytes);
+ assert(newOffset >= 0 && newOffset < bdata.lengthInBytes);
_offset = newOffset;
}
@@ -91,26 +85,16 @@
int readByte({bool signed = false}) => readBytes(1, signed: signed);
int readWord() => readBytes(wordSize);
- String readNullTerminatedString({int? maxSize}) {
- final start = _offset;
- int end = maxSize != null ? _offset + maxSize : bdata.lengthInBytes;
- for (; _offset < end; _offset++) {
- if (bdata.getUint8(_offset) == 0) {
- end = _offset;
- _offset++; // Move reader past null terminator.
- break;
+ String readNullTerminatedString() {
+ final start = bdata.offsetInBytes + _offset;
+ for (var i = 0; _offset + i < bdata.lengthInBytes; i++) {
+ if (bdata.getUint8(_offset + i) == 0) {
+ _offset += i + 1;
+ return String.fromCharCodes(bdata.buffer.asUint8List(start, i));
}
}
return String.fromCharCodes(
- bdata.buffer.asUint8List(bdata.offsetInBytes + start, end - start));
- }
-
- String readFixedLengthNullTerminatedString(int maxSize) {
- final start = _offset;
- final str = readNullTerminatedString(maxSize: maxSize);
- // Ensure reader points past fixed space, not at end of string within it.
- _offset = start + maxSize;
- return str;
+ bdata.buffer.asUint8List(start, bdata.lengthInBytes - _offset));
}
int readLEB128EncodedInteger({bool signed = false}) {
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 13534d8..31d6f25 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -318,13 +318,6 @@
return Object::null();
}
-DEFINE_NATIVE_ENTRY(Internal_randomAddressInsideAllocateObjectStub, 0, 0) {
- auto& stub = Code::Handle(
- zone, isolate->group()->object_store()->allocate_object_stub());
- const uword random_offset = isolate->random()->NextUInt32() % stub.Size();
- return Smi::New(stub.EntryPoint() + random_offset);
-}
-
static bool ExtractInterfaceTypeArgs(Zone* zone,
const Class& instance_cls,
const TypeArguments& instance_type_args,
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
index 9d291b3..c422f18 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_program.dart
@@ -4,8 +4,6 @@
// Test that the full stacktrace in an error object matches the stacktrace
// handed to the catch clause.
-import 'dart:_internal' show VMInternalsForTesting;
-
import "package:expect/expect.dart";
class C {
@@ -17,6 +15,5 @@
foo(c) => bar(c);
main() {
- print(VMInternalsForTesting.randomAddressInsideAllocateObjectStub());
var a = foo(new C());
}
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
index b85c992..d8cb33f 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
@@ -6,8 +6,9 @@
// compile-time will be used at runtime (irrespective if other values were
// passed to the runtime).
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
+
import "dart:async";
-import "dart:convert";
import "dart:io";
import 'package:expect/expect.dart';
@@ -37,11 +38,8 @@
}
await withTempDir('dwarf-flag-test', (String tempDir) async {
- // We have to use the program in its original location so it can use
- // the dart:_internal library (as opposed to adding it as an OtherResources
- // option to the test).
- final script = path.join(sdkDir, 'runtime', 'tests', 'vm', 'dart',
- 'use_dwarf_stack_traces_flag_program.dart');
+ final cwDir = path.dirname(Platform.script.toFilePath());
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
@@ -78,252 +76,123 @@
]);
// Run the resulting Dwarf-AOT compiled script.
-
- final output1 = await runTestProgram(aotRuntime,
- <String>['--dwarf-stack-traces-mode', scriptDwarfSnapshot, scriptDill]);
- final output2 = await runTestProgram(aotRuntime, <String>[
+ final dwarfTrace1 = await runError(aotRuntime, <String>[
+ '--dwarf-stack-traces-mode',
+ scriptDwarfSnapshot,
+ scriptDill,
+ ]);
+ final dwarfTrace2 = await runError(aotRuntime, <String>[
'--no-dwarf-stack-traces-mode',
scriptDwarfSnapshot,
- scriptDill
+ scriptDill,
]);
// Run the resulting non-Dwarf-AOT compiled script.
- final nonDwarfTrace1 = (await runTestProgram(aotRuntime, <String>[
+ final nonDwarfTrace1 = await runError(aotRuntime, <String>[
'--dwarf-stack-traces-mode',
scriptNonDwarfSnapshot,
scriptDill,
- ]))
- .trace;
- final nonDwarfTrace2 = (await runTestProgram(aotRuntime, <String>[
+ ]);
+ final nonDwarfTrace2 = await runError(aotRuntime, <String>[
'--no-dwarf-stack-traces-mode',
scriptNonDwarfSnapshot,
scriptDill,
- ]))
- .trace;
+ ]);
// Ensure the result is based off the flag passed to gen_snapshot, not
// the one passed to the runtime.
Expect.deepEquals(nonDwarfTrace1, nonDwarfTrace2);
- // Check with DWARF from separate debugging information.
- await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfDebugInfo);
- // Check with DWARF in generated snapshot.
- await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfSnapshot);
+ // For DWARF stack traces, we can't guarantee that the stack traces are
+ // textually equal on all platforms, but if we retrieve the PC offsets
+ // out of the stack trace, those should be equal.
+ final tracePCOffsets1 = collectPCOffsets(dwarfTrace1);
+ final tracePCOffsets2 = collectPCOffsets(dwarfTrace2);
+ Expect.deepEquals(tracePCOffsets1, tracePCOffsets2);
- if (Platform.isLinux || Platform.isMacOS) {
- final scriptAssembly = path.join(tempDir, 'dwarf_assembly.S');
- final scriptDwarfAssemblyDebugInfo =
- path.join(tempDir, 'dwarf_assembly_info.so');
- final scriptDwarfAssemblySnapshot =
- path.join(tempDir, 'dwarf_assembly.so');
- // We get a separate .dSYM bundle on MacOS.
- final scriptDwarfAssemblyDebugSnapshot =
- scriptDwarfAssemblySnapshot + (Platform.isMacOS ? '.dSYM' : '');
+ // Check that translating the DWARF stack trace (without internal frames)
+ // matches the symbolic stack trace.
+ final dwarf = Dwarf.fromFile(scriptDwarfDebugInfo)!;
- await run(genSnapshot, <String>[
- // We test --dwarf-stack-traces-mode, not --dwarf-stack-traces, because
- // the latter is a handler that sets the former and also may change
- // other flags. This way, we limit the difference between the two
- // snapshots and also directly test the flag saved as a VM global flag.
- '--dwarf-stack-traces-mode',
- '--save-debugging-info=$scriptDwarfAssemblyDebugInfo',
- '--snapshot-kind=app-aot-assembly',
- '--assembly=$scriptAssembly',
- scriptDill,
- ]);
-
- await assembleSnapshot(scriptAssembly, scriptDwarfAssemblySnapshot,
- debug: true);
-
- // Run the resulting Dwarf-AOT compiled script.
- final assemblyOutput1 = await runTestProgram(aotRuntime, <String>[
- '--dwarf-stack-traces-mode',
- scriptDwarfAssemblySnapshot,
- scriptDill,
- ]);
- final assemblyOutput2 = await runTestProgram(aotRuntime, <String>[
- '--no-dwarf-stack-traces-mode',
- scriptDwarfAssemblySnapshot,
- scriptDill,
- ]);
-
- // Check with DWARF in assembled snapshot.
- await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
- scriptDwarfAssemblyDebugSnapshot,
- fromAssembly: true);
- // Check with DWARF from separate debugging information.
- await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
- scriptDwarfAssemblyDebugInfo,
- fromAssembly: true);
- }
- });
-}
-
-class DwarfTestOutput {
- final List<String> trace;
- final int allocateObjectAddress;
-
- DwarfTestOutput(this.trace, this.allocateObjectAddress);
-}
-
-Future<void> compareTraces(List<String> nonDwarfTrace, DwarfTestOutput output1,
- DwarfTestOutput output2, String dwarfPath,
- {bool fromAssembly = false}) async {
- // For DWARF stack traces, we can't guarantee that the stack traces are
- // textually equal on all platforms, but if we retrieve the PC offsets
- // out of the stack trace, those should be equal.
- final tracePCOffsets1 = collectPCOffsets(output1.trace);
- final tracePCOffsets2 = collectPCOffsets(output2.trace);
- Expect.deepEquals(tracePCOffsets1, tracePCOffsets2);
-
- // Check that translating the DWARF stack trace (without internal frames)
- // matches the symbolic stack trace.
- print("Reading DWARF info from ${dwarfPath}");
- final dwarf = Dwarf.fromFile(dwarfPath);
- Expect.isNotNull(dwarf);
-
- // Check that build IDs match for traces from running ELF snapshots.
- if (!fromAssembly) {
- Expect.isNotNull(dwarf!.buildId);
+ // Check that build IDs match for traces.
+ Expect.isNotNull(dwarf.buildId);
print('Dwarf build ID: "${dwarf.buildId!}"');
// We should never generate an all-zero build ID.
Expect.notEquals(dwarf.buildId, "00000000000000000000000000000000");
// This is a common failure case as well, when HashBitsContainer ends up
// hashing over seemingly empty sections.
Expect.notEquals(dwarf.buildId, "01000000010000000100000001000000");
- final buildId1 = buildId(output1.trace);
+ final buildId1 = buildId(dwarfTrace1);
Expect.isFalse(buildId1.isEmpty);
print('Trace 1 build ID: "${buildId1}"');
Expect.equals(dwarf.buildId, buildId1);
- final buildId2 = buildId(output2.trace);
+ final buildId2 = buildId(dwarfTrace2);
Expect.isFalse(buildId2.isEmpty);
print('Trace 2 build ID: "${buildId2}"');
Expect.equals(dwarf.buildId, buildId2);
- }
- final decoder = DwarfStackTraceDecoder(dwarf!);
- // Run on the second trace just for the side effect of getting the header
- // information so we can get the PC offset of the output address.
- await Stream.fromIterable(output2.trace).transform(decoder).toList();
- final allocateObjectPCOffset2 =
- decoder.offsetOf(output2.allocateObjectAddress);
- final translatedDwarfTrace1 =
- await Stream.fromIterable(output1.trace).transform(decoder).toList();
- final allocateObjectPCOffset1 =
- decoder.offsetOf(output1.allocateObjectAddress);
+ final translatedDwarfTrace1 = await Stream.fromIterable(dwarfTrace1)
+ .transform(DwarfStackTraceDecoder(dwarf))
+ .toList();
- print('Offset of first stub address '
- '0x${output1.allocateObjectAddress.toRadixString(16)}'
- ' is $allocateObjectPCOffset1');
- print('Offset of second stub address '
- '0x${output2.allocateObjectAddress.toRadixString(16)}'
- ' is $allocateObjectPCOffset2');
+ final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
+ final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace1);
- Expect.isNotNull(allocateObjectPCOffset1);
- Expect.isNotNull(allocateObjectPCOffset2);
- final allocateObjectRelocatedAddress1 =
- dwarf.virtualAddressOf(allocateObjectPCOffset1!);
- final allocateObjectRelocatedAddress2 =
- dwarf.virtualAddressOf(allocateObjectPCOffset2!);
+ print('Stack frames from translated non-symbolic stack trace:');
+ translatedStackFrames.forEach(print);
+ print('');
- final allocateObjectCallInfo1 = dwarf.callInfoFor(
- allocateObjectRelocatedAddress1,
- includeInternalFrames: true);
- final allocateObjectCallInfo2 = dwarf.callInfoFor(
- allocateObjectRelocatedAddress2,
- includeInternalFrames: true);
+ print('Stack frames from original symbolic stack trace:');
+ originalStackFrames.forEach(print);
+ print('');
- Expect.isNotNull(allocateObjectCallInfo1);
- Expect.isNotNull(allocateObjectCallInfo2);
- Expect.equals(allocateObjectCallInfo1!.length, 1);
- Expect.equals(allocateObjectCallInfo2!.length, 1);
- Expect.isTrue(
- allocateObjectCallInfo1.first is StubCallInfo, 'is not a StubCall');
- Expect.isTrue(
- allocateObjectCallInfo2.first is StubCallInfo, 'is not a StubCall');
- final stubCall1 = allocateObjectCallInfo1.first as StubCallInfo;
- final stubCall2 = allocateObjectCallInfo2.first as StubCallInfo;
- Expect.equals(stubCall1.name, stubCall2.name);
- Expect.contains('AllocateObject', stubCall1.name);
- Expect.contains('AllocateObject', stubCall2.name);
+ Expect.isTrue(translatedStackFrames.length > 0);
+ Expect.isTrue(originalStackFrames.length > 0);
- print("Successfully matched AllocateObject stub addresses");
- print("");
+ // In symbolic mode, we don't store column information to avoid an increase
+ // in size of CodeStackMaps. Thus, we need to strip any columns from the
+ // translated non-symbolic stack to compare them via equality.
+ final columnStrippedTranslated = removeColumns(translatedStackFrames);
- final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
- final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace);
+ print('Stack frames from translated non-symbolic stack trace, no columns:');
+ columnStrippedTranslated.forEach(print);
+ print('');
- print('Stack frames from translated non-symbolic stack trace:');
- translatedStackFrames.forEach(print);
- print('');
+ Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
- print('Stack frames from original symbolic stack trace:');
- originalStackFrames.forEach(print);
- print('');
+ // Since we compiled directly to ELF, there should be a DSO base address
+ // in the stack trace header and 'virt' markers in the stack frames.
- Expect.isTrue(translatedStackFrames.length > 0);
- Expect.isTrue(originalStackFrames.length > 0);
+ // The offsets of absolute addresses from their respective DSO base
+ // should be the same for both traces.
+ final dsoBase1 = dsoBaseAddresses(dwarfTrace1).single;
+ final dsoBase2 = dsoBaseAddresses(dwarfTrace2).single;
- // In symbolic mode, we don't store column information to avoid an increase
- // in size of CodeStackMaps. Thus, we need to strip any columns from the
- // translated non-symbolic stack to compare them via equality.
- final columnStrippedTranslated = removeColumns(translatedStackFrames);
+ final absTrace1 = absoluteAddresses(dwarfTrace1);
+ final absTrace2 = absoluteAddresses(dwarfTrace2);
- print('Stack frames from translated non-symbolic stack trace, no columns:');
- columnStrippedTranslated.forEach(print);
- print('');
+ final relocatedFromDso1 = absTrace1.map((a) => a - dsoBase1);
+ final relocatedFromDso2 = absTrace2.map((a) => a - dsoBase2);
- Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
+ Expect.deepEquals(relocatedFromDso1, relocatedFromDso2);
- // Since we compiled directly to ELF, there should be a DSO base address
- // in the stack trace header and 'virt' markers in the stack frames.
+ // The relocated addresses marked with 'virt' should match between the
+ // different runs, and they should also match the relocated address
+ // calculated from the PCOffset for each frame as well as the relocated
+ // address for each frame calculated using the respective DSO base.
+ final virtTrace1 = explicitVirtualAddresses(dwarfTrace1);
+ final virtTrace2 = explicitVirtualAddresses(dwarfTrace2);
- // The offsets of absolute addresses from their respective DSO base
- // should be the same for both traces.
- final dsoBase1 = dsoBaseAddresses(output1.trace).single;
- final dsoBase2 = dsoBaseAddresses(output2.trace).single;
+ Expect.deepEquals(virtTrace1, virtTrace2);
- final absTrace1 = absoluteAddresses(output1.trace);
- final absTrace2 = absoluteAddresses(output2.trace);
+ Expect.deepEquals(
+ virtTrace1, tracePCOffsets1.map((o) => o.virtualAddressIn(dwarf)));
+ Expect.deepEquals(
+ virtTrace2, tracePCOffsets2.map((o) => o.virtualAddressIn(dwarf)));
- final relocatedFromDso1 = absTrace1.map((a) => a - dsoBase1);
- final relocatedFromDso2 = absTrace2.map((a) => a - dsoBase2);
-
- Expect.deepEquals(relocatedFromDso1, relocatedFromDso2);
-
- // We don't print 'virt' relocated addresses when running assembled snapshots.
- if (fromAssembly) return;
-
- // The relocated addresses marked with 'virt' should match between the
- // different runs, and they should also match the relocated address
- // calculated from the PCOffset for each frame as well as the relocated
- // address for each frame calculated using the respective DSO base.
- final virtTrace1 = explicitVirtualAddresses(output1.trace);
- final virtTrace2 = explicitVirtualAddresses(output2.trace);
-
- Expect.deepEquals(virtTrace1, virtTrace2);
-
- Expect.deepEquals(
- virtTrace1, tracePCOffsets1.map((o) => o.virtualAddressIn(dwarf)));
- Expect.deepEquals(
- virtTrace2, tracePCOffsets2.map((o) => o.virtualAddressIn(dwarf)));
-
- Expect.deepEquals(virtTrace1, relocatedFromDso1);
- Expect.deepEquals(virtTrace2, relocatedFromDso2);
-}
-
-Future<DwarfTestOutput> runTestProgram(
- String executable, List<String> args) async {
- final result = await runHelper(executable, args);
-
- if (result.exitCode == 0) {
- throw 'Command did not fail with non-zero exit code';
- }
- Expect.isTrue(result.stdout.isNotEmpty);
- Expect.isTrue(result.stderr.isNotEmpty);
-
- return DwarfTestOutput(
- LineSplitter.split(result.stderr).toList(), int.parse(result.stdout));
+ Expect.deepEquals(virtTrace1, relocatedFromDso1);
+ Expect.deepEquals(virtTrace2, relocatedFromDso2);
+ });
}
final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
diff --git a/runtime/tests/vm/dart/use_flag_test_helper.dart b/runtime/tests/vm/dart/use_flag_test_helper.dart
index 5cd09d9..431fce5 100644
--- a/runtime/tests/vm/dart/use_flag_test_helper.dart
+++ b/runtime/tests/vm/dart/use_flag_test_helper.dart
@@ -38,8 +38,7 @@
return Directory(clangDir).existsSync() ? clangDir : null;
}
-Future<void> assembleSnapshot(String assemblyPath, String snapshotPath,
- {bool debug = false}) async {
+Future<void> assembleSnapshot(String assemblyPath, String snapshotPath) async {
if (!Platform.isLinux && !Platform.isMacOS) {
throw "Unsupported platform ${Platform.operatingSystem} for assembling";
}
@@ -63,11 +62,6 @@
if (Platform.isMacOS) {
shared = '-dynamiclib';
- if (buildDir.endsWith('ARM64')) {
- // ld: dynamic main executables must link with libSystem.dylib for
- // architecture arm64
- ldFlags.add('-lSystem');
- }
// Tell Mac linker to give up generating eh_frame from dwarf.
ldFlags.add('-Wl,-no_compact_unwind');
} else if (buildDir.endsWith('SIMARM')) {
@@ -79,9 +73,6 @@
if (buildDir.endsWith('X64') || buildDir.endsWith('SIMARM64')) {
ccFlags.add('-m64');
}
- if (debug) {
- ccFlags.add('-g');
- }
await run(cc, <String>[
...ccFlags,
@@ -167,7 +158,9 @@
Expect.isTrue(result.stdout.isNotEmpty);
Expect.isTrue(result.stderr.isEmpty);
- return LineSplitter.split(result.stdout).toList(growable: false);
+ return await Stream.value(result.stdout as String)
+ .transform(const LineSplitter())
+ .toList();
}
Future<List<String>> runError(String executable, List<String> args) async {
@@ -179,7 +172,9 @@
Expect.isTrue(result.stdout.isEmpty);
Expect.isTrue(result.stderr.isNotEmpty);
- return LineSplitter.split(result.stderr).toList(growable: false);
+ return await Stream.value(result.stderr as String)
+ .transform(const LineSplitter())
+ .toList();
}
const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
diff --git a/runtime/tests/vm/dart/use_resolve_dwarf_paths_flag_test.dart b/runtime/tests/vm/dart/use_resolve_dwarf_paths_flag_test.dart
index 9962f97..30d90d5 100644
--- a/runtime/tests/vm/dart/use_resolve_dwarf_paths_flag_test.dart
+++ b/runtime/tests/vm/dart/use_resolve_dwarf_paths_flag_test.dart
@@ -5,7 +5,7 @@
// This test checks that --resolve-dwarf-paths outputs absolute and relative
// paths in DWARF information.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:async";
import "dart:io";
@@ -38,8 +38,7 @@
await withTempDir('dwarf-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart/use_save_debugging_info_flag_program.dart b/runtime/tests/vm/dart/use_save_debugging_info_flag_program.dart
deleted file mode 100644
index 51d3c4b..0000000
--- a/runtime/tests/vm/dart/use_save_debugging_info_flag_program.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Test that the full stacktrace in an error object matches the stacktrace
-// handed to the catch clause.
-
-import "package:expect/expect.dart";
-
-class C {
- // operator*(o) is missing to trigger a noSuchMethodError when a C object
- // is used in the multiplication below.
-}
-
-bar(c) => c * 4;
-foo(c) => bar(c);
-
-main() {
- var a = foo(new C());
-}
diff --git a/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart b/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
index f79ada1..2bd55a2 100644
--- a/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
+++ b/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
@@ -6,7 +6,7 @@
// for stripped ELF output, and that using the debugging information to look
// up stripped stack trace information matches the non-stripped version.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:io";
import "dart:math";
@@ -41,8 +41,8 @@
await withTempDir('save-debug-info-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart/use_strip_flag_test.dart b/runtime/tests/vm/dart/use_strip_flag_test.dart
index 6dbd53b..5025c84 100644
--- a/runtime/tests/vm/dart/use_strip_flag_test.dart
+++ b/runtime/tests/vm/dart/use_strip_flag_test.dart
@@ -6,7 +6,7 @@
// ELF and assembly output. This test is currently very weak, in that it just
// checks that the stripped version is strictly smaller than the unstripped one.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:io";
@@ -34,9 +34,8 @@
await withTempDir('strip-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- // We can just reuse the program for the use_save_debugging_info_flag test.
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart/use_trace_precompiler_flag_test.dart b/runtime/tests/vm/dart/use_trace_precompiler_flag_test.dart
index 8d9123f..7ea2d60 100644
--- a/runtime/tests/vm/dart/use_trace_precompiler_flag_test.dart
+++ b/runtime/tests/vm/dart/use_trace_precompiler_flag_test.dart
@@ -5,7 +5,7 @@
// This test ensures that --trace-precompiler runs without issue and prints
// valid JSON for reasons to retain objects.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:convert";
import "dart:io";
@@ -37,9 +37,8 @@
await withTempDir('trace-precompiler-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- // We can just reuse the program for the use_save_debugging_info_flag test.
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_program.dart b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_program.dart
index 8e6838f..a4e399e 100644
--- a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_program.dart
+++ b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_program.dart
@@ -6,8 +6,6 @@
// @dart = 2.9
-import 'dart:_internal' show VMInternalsForTesting;
-
import "package:expect/expect.dart";
class C {
@@ -19,6 +17,5 @@
foo(c) => bar(c);
main() {
- print(VMInternalsForTesting.randomAddressInsideAllocateObjectStub());
var a = foo(new C());
}
diff --git a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
index 7bd3716..5850250 100644
--- a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
@@ -8,8 +8,9 @@
// compile-time will be used at runtime (irrespective if other values were
// passed to the runtime).
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
+
import "dart:async";
-import "dart:convert";
import "dart:io";
import 'package:expect/expect.dart';
@@ -39,11 +40,8 @@
}
await withTempDir('dwarf-flag-test', (String tempDir) async {
- // We have to use the program in its original location so it can use
- // the dart:_internal library (as opposed to adding it as an OtherResources
- // option to the test).
- final script = path.join(sdkDir, 'runtime', 'tests', 'vm', 'dart',
- 'use_dwarf_stack_traces_flag_program.dart');
+ final cwDir = path.dirname(Platform.script.toFilePath());
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
@@ -80,112 +78,46 @@
]);
// Run the resulting Dwarf-AOT compiled script.
-
- final output1 = await runTestProgram(aotRuntime,
- <String>['--dwarf-stack-traces-mode', scriptDwarfSnapshot, scriptDill]);
- final output2 = await runTestProgram(aotRuntime, <String>[
+ final dwarfTrace1 = await runError(aotRuntime, <String>[
+ '--dwarf-stack-traces-mode',
+ scriptDwarfSnapshot,
+ scriptDill,
+ ]);
+ final dwarfTrace2 = await runError(aotRuntime, <String>[
'--no-dwarf-stack-traces-mode',
scriptDwarfSnapshot,
- scriptDill
+ scriptDill,
]);
// Run the resulting non-Dwarf-AOT compiled script.
- final nonDwarfTrace1 = (await runTestProgram(aotRuntime, <String>[
+ final nonDwarfTrace1 = await runError(aotRuntime, <String>[
'--dwarf-stack-traces-mode',
scriptNonDwarfSnapshot,
scriptDill,
- ]))
- .trace;
- final nonDwarfTrace2 = (await runTestProgram(aotRuntime, <String>[
+ ]);
+ final nonDwarfTrace2 = await runError(aotRuntime, <String>[
'--no-dwarf-stack-traces-mode',
scriptNonDwarfSnapshot,
scriptDill,
- ]))
- .trace;
+ ]);
// Ensure the result is based off the flag passed to gen_snapshot, not
// the one passed to the runtime.
Expect.deepEquals(nonDwarfTrace1, nonDwarfTrace2);
- // Check with DWARF from separate debugging information.
- await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfDebugInfo);
- // Check with DWARF in generated snapshot.
- await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfSnapshot);
+ // For DWARF stack traces, we can't guarantee that the stack traces are
+ // textually equal on all platforms, but if we retrieve the PC offsets
+ // out of the stack trace, those should be equal.
+ final tracePCOffsets1 = collectPCOffsets(dwarfTrace1);
+ final tracePCOffsets2 = collectPCOffsets(dwarfTrace2);
+ Expect.deepEquals(tracePCOffsets1, tracePCOffsets2);
- if (Platform.isLinux || Platform.isMacOS) {
- final scriptAssembly = path.join(tempDir, 'dwarf_assembly.S');
- final scriptDwarfAssemblyDebugInfo =
- path.join(tempDir, 'dwarf_assembly_info.so');
- final scriptDwarfAssemblySnapshot =
- path.join(tempDir, 'dwarf_assembly.so');
- // We get a separate .dSYM bundle on MacOS.
- final scriptDwarfAssemblyDebugSnapshot =
- scriptDwarfAssemblySnapshot + (Platform.isMacOS ? '.dSYM' : '');
+ // Check that translating the DWARF stack trace (without internal frames)
+ // matches the symbolic stack trace.
+ final dwarf = Dwarf.fromFile(scriptDwarfDebugInfo);
+ Expect.isNotNull(dwarf);
- await run(genSnapshot, <String>[
- // We test --dwarf-stack-traces-mode, not --dwarf-stack-traces, because
- // the latter is a handler that sets the former and also may change
- // other flags. This way, we limit the difference between the two
- // snapshots and also directly test the flag saved as a VM global flag.
- '--dwarf-stack-traces-mode',
- '--save-debugging-info=$scriptDwarfAssemblyDebugInfo',
- '--snapshot-kind=app-aot-assembly',
- '--assembly=$scriptAssembly',
- scriptDill,
- ]);
-
- await assembleSnapshot(scriptAssembly, scriptDwarfAssemblySnapshot,
- debug: true);
-
- // Run the resulting Dwarf-AOT compiled script.
- final assemblyOutput1 = await runTestProgram(aotRuntime, <String>[
- '--dwarf-stack-traces-mode',
- scriptDwarfAssemblySnapshot,
- scriptDill,
- ]);
- final assemblyOutput2 = await runTestProgram(aotRuntime, <String>[
- '--no-dwarf-stack-traces-mode',
- scriptDwarfAssemblySnapshot,
- scriptDill,
- ]);
-
- // Check with DWARF in assembled snapshot.
- await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
- scriptDwarfAssemblyDebugSnapshot,
- fromAssembly: true);
- // Check with DWARF from separate debugging information.
- await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
- scriptDwarfAssemblyDebugInfo,
- fromAssembly: true);
- }
- });
-}
-
-class DwarfTestOutput {
- final List<String> trace;
- final int allocateObjectAddress;
-
- DwarfTestOutput(this.trace, this.allocateObjectAddress);
-}
-
-Future<void> compareTraces(List<String> nonDwarfTrace, DwarfTestOutput output1,
- DwarfTestOutput output2, String dwarfPath,
- {bool fromAssembly = false}) async {
- // For DWARF stack traces, we can't guarantee that the stack traces are
- // textually equal on all platforms, but if we retrieve the PC offsets
- // out of the stack trace, those should be equal.
- final tracePCOffsets1 = collectPCOffsets(output1.trace);
- final tracePCOffsets2 = collectPCOffsets(output2.trace);
- Expect.deepEquals(tracePCOffsets1, tracePCOffsets2);
-
- // Check that translating the DWARF stack trace (without internal frames)
- // matches the symbolic stack trace.
- print("Reading DWARF info from ${dwarfPath}");
- final dwarf = Dwarf.fromFile(dwarfPath);
- Expect.isNotNull(dwarf);
-
- // Check that build IDs match for traces from running ELF snapshots.
- if (!fromAssembly) {
+ // Check that build IDs match for traces.
Expect.isNotNull(dwarf.buildId);
print('Dwarf build ID: "${dwarf.buildId}"');
// We should never generate an all-zero build ID.
@@ -193,139 +125,77 @@
// This is a common failure case as well, when HashBitsContainer ends up
// hashing over seemingly empty sections.
Expect.notEquals(dwarf.buildId, "01000000010000000100000001000000");
- final buildId1 = buildId(output1.trace);
+ final buildId1 = buildId(dwarfTrace1);
Expect.isFalse(buildId1.isEmpty);
print('Trace 1 build ID: "${buildId1}"');
Expect.equals(dwarf.buildId, buildId1);
- final buildId2 = buildId(output2.trace);
+ final buildId2 = buildId(dwarfTrace2);
Expect.isFalse(buildId2.isEmpty);
print('Trace 2 build ID: "${buildId2}"');
Expect.equals(dwarf.buildId, buildId2);
- }
- final decoder = DwarfStackTraceDecoder(dwarf);
- // Run on the second trace just for the side effect of getting the header
- // information so we can get the PC offset of the output address.
- await Stream.fromIterable(output2.trace).transform(decoder).toList();
- final allocateObjectPCOffset2 =
- decoder.offsetOf(output2.allocateObjectAddress);
- final translatedDwarfTrace1 =
- await Stream.fromIterable(output1.trace).transform(decoder).toList();
- final allocateObjectPCOffset1 =
- decoder.offsetOf(output1.allocateObjectAddress);
+ final translatedDwarfTrace1 = await Stream.fromIterable(dwarfTrace1)
+ .transform(DwarfStackTraceDecoder(dwarf))
+ .toList();
- print('Offset of first stub address '
- '0x${output1.allocateObjectAddress.toRadixString(16)}'
- ' is $allocateObjectPCOffset1');
- print('Offset of second stub address '
- '0x${output2.allocateObjectAddress.toRadixString(16)}'
- ' is $allocateObjectPCOffset2');
+ final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
+ final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace1);
- Expect.isNotNull(allocateObjectPCOffset1);
- Expect.isNotNull(allocateObjectPCOffset2);
- final allocateObjectRelocatedAddress1 =
- dwarf.virtualAddressOf(allocateObjectPCOffset1);
- final allocateObjectRelocatedAddress2 =
- dwarf.virtualAddressOf(allocateObjectPCOffset2);
+ print('Stack frames from translated non-symbolic stack trace:');
+ translatedStackFrames.forEach(print);
+ print('');
- final allocateObjectCallInfo1 = dwarf.callInfoFor(
- allocateObjectRelocatedAddress1,
- includeInternalFrames: true);
- final allocateObjectCallInfo2 = dwarf.callInfoFor(
- allocateObjectRelocatedAddress2,
- includeInternalFrames: true);
+ print('Stack frames from original symbolic stack trace:');
+ originalStackFrames.forEach(print);
+ print('');
- Expect.isNotNull(allocateObjectCallInfo1);
- Expect.isNotNull(allocateObjectCallInfo2);
- Expect.equals(allocateObjectCallInfo1.length, 1);
- Expect.equals(allocateObjectCallInfo2.length, 1);
- Expect.isTrue(
- allocateObjectCallInfo1.first is StubCallInfo, 'is not a StubCall');
- Expect.isTrue(
- allocateObjectCallInfo2.first is StubCallInfo, 'is not a StubCall');
- final stubCall1 = allocateObjectCallInfo1.first as StubCallInfo;
- final stubCall2 = allocateObjectCallInfo2.first as StubCallInfo;
- Expect.equals(stubCall1.name, stubCall2.name);
- Expect.contains('AllocateObject', stubCall1.name);
- Expect.contains('AllocateObject', stubCall2.name);
+ Expect.isTrue(translatedStackFrames.length > 0);
+ Expect.isTrue(originalStackFrames.length > 0);
- print("Successfully matched AllocateObject stub addresses");
- print("");
+ // In symbolic mode, we don't store column information to avoid an increase
+ // in size of CodeStackMaps. Thus, we need to strip any columns from the
+ // translated non-symbolic stack to compare them via equality.
+ final columnStrippedTranslated = removeColumns(translatedStackFrames);
- final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
- final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace);
+ print('Stack frames from translated non-symbolic stack trace, no columns:');
+ columnStrippedTranslated.forEach(print);
+ print('');
- print('Stack frames from translated non-symbolic stack trace:');
- translatedStackFrames.forEach(print);
- print('');
+ Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
- print('Stack frames from original symbolic stack trace:');
- originalStackFrames.forEach(print);
- print('');
+ // Since we compiled directly to ELF, there should be a DSO base address
+ // in the stack trace header and 'virt' markers in the stack frames.
- Expect.isTrue(translatedStackFrames.length > 0);
- Expect.isTrue(originalStackFrames.length > 0);
+ // The offsets of absolute addresses from their respective DSO base
+ // should be the same for both traces.
+ final dsoBase1 = dsoBaseAddresses(dwarfTrace1).single;
+ final dsoBase2 = dsoBaseAddresses(dwarfTrace2).single;
- // In symbolic mode, we don't store column information to avoid an increase
- // in size of CodeStackMaps. Thus, we need to strip any columns from the
- // translated non-symbolic stack to compare them via equality.
- final columnStrippedTranslated = removeColumns(translatedStackFrames);
+ final absTrace1 = absoluteAddresses(dwarfTrace1);
+ final absTrace2 = absoluteAddresses(dwarfTrace2);
- print('Stack frames from translated non-symbolic stack trace, no columns:');
- columnStrippedTranslated.forEach(print);
- print('');
+ final relocatedFromDso1 = absTrace1.map((a) => a - dsoBase1);
+ final relocatedFromDso2 = absTrace2.map((a) => a - dsoBase2);
- Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
+ Expect.deepEquals(relocatedFromDso1, relocatedFromDso2);
- // Since we compiled directly to ELF, there should be a DSO base address
- // in the stack trace header and 'virt' markers in the stack frames.
+ // The relocated addresses marked with 'virt' should match between the
+ // different runs, and they should also match the relocated address
+ // calculated from the PCOffset for each frame as well as the relocated
+ // address for each frame calculated using the respective DSO base.
+ final virtTrace1 = explicitVirtualAddresses(dwarfTrace1);
+ final virtTrace2 = explicitVirtualAddresses(dwarfTrace2);
- // The offsets of absolute addresses from their respective DSO base
- // should be the same for both traces.
- final dsoBase1 = dsoBaseAddresses(output1.trace).single;
- final dsoBase2 = dsoBaseAddresses(output2.trace).single;
+ Expect.deepEquals(virtTrace1, virtTrace2);
- final absTrace1 = absoluteAddresses(output1.trace);
- final absTrace2 = absoluteAddresses(output2.trace);
+ Expect.deepEquals(
+ virtTrace1, tracePCOffsets1.map((o) => o.virtualAddressIn(dwarf)));
+ Expect.deepEquals(
+ virtTrace2, tracePCOffsets2.map((o) => o.virtualAddressIn(dwarf)));
- final relocatedFromDso1 = absTrace1.map((a) => a - dsoBase1);
- final relocatedFromDso2 = absTrace2.map((a) => a - dsoBase2);
-
- Expect.deepEquals(relocatedFromDso1, relocatedFromDso2);
-
- // We don't print 'virt' relocated addresses when running assembled snapshots.
- if (fromAssembly) return;
-
- // The relocated addresses marked with 'virt' should match between the
- // different runs, and they should also match the relocated address
- // calculated from the PCOffset for each frame as well as the relocated
- // address for each frame calculated using the respective DSO base.
- final virtTrace1 = explicitVirtualAddresses(output1.trace);
- final virtTrace2 = explicitVirtualAddresses(output2.trace);
-
- Expect.deepEquals(virtTrace1, virtTrace2);
-
- Expect.deepEquals(
- virtTrace1, tracePCOffsets1.map((o) => o.virtualAddressIn(dwarf)));
- Expect.deepEquals(
- virtTrace2, tracePCOffsets2.map((o) => o.virtualAddressIn(dwarf)));
-
- Expect.deepEquals(virtTrace1, relocatedFromDso1);
- Expect.deepEquals(virtTrace2, relocatedFromDso2);
-}
-
-Future<DwarfTestOutput> runTestProgram(
- String executable, List<String> args) async {
- final result = await runHelper(executable, args);
-
- if (result.exitCode == 0) {
- throw 'Command did not fail with non-zero exit code';
- }
- Expect.isTrue(result.stdout.isNotEmpty);
- Expect.isTrue(result.stderr.isNotEmpty);
-
- return DwarfTestOutput(
- LineSplitter.split(result.stderr).toList(), int.parse(result.stdout));
+ Expect.deepEquals(virtTrace1, relocatedFromDso1);
+ Expect.deepEquals(virtTrace2, relocatedFromDso2);
+ });
}
final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
diff --git a/runtime/tests/vm/dart_2/use_flag_test_helper.dart b/runtime/tests/vm/dart_2/use_flag_test_helper.dart
index 8fdf89b..b408f42 100644
--- a/runtime/tests/vm/dart_2/use_flag_test_helper.dart
+++ b/runtime/tests/vm/dart_2/use_flag_test_helper.dart
@@ -40,8 +40,7 @@
return Directory(clangDir).existsSync() ? clangDir : null;
}
-Future<void> assembleSnapshot(String assemblyPath, String snapshotPath,
- {bool debug = false}) async {
+Future<void> assembleSnapshot(String assemblyPath, String snapshotPath) async {
if (!Platform.isLinux && !Platform.isMacOS) {
throw "Unsupported platform ${Platform.operatingSystem} for assembling";
}
@@ -64,11 +63,6 @@
if (Platform.isMacOS) {
shared = '-dynamiclib';
- if (buildDir.endsWith('ARM64')) {
- // ld: dynamic main executables must link with libSystem.dylib for
- // architecture arm64
- ldFlags.add('-lSystem');
- }
// Tell Mac linker to give up generating eh_frame from dwarf.
ldFlags.add('-Wl,-no_compact_unwind');
} else if (buildDir.endsWith('SIMARM')) {
@@ -80,9 +74,6 @@
if (buildDir.endsWith('X64') || buildDir.endsWith('SIMARM64')) {
ccFlags.add('-m64');
}
- if (debug) {
- ccFlags.add('-g');
- }
await run(cc, <String>[
...ccFlags,
@@ -167,7 +158,9 @@
Expect.isTrue(result.stdout.isNotEmpty);
Expect.isTrue(result.stderr.isEmpty);
- return LineSplitter.split(result.stdout).toList(growable: false);
+ return await Stream.value(result.stdout as String)
+ .transform(const LineSplitter())
+ .toList();
}
Future<List<String>> runError(String executable, List<String> args) async {
@@ -179,7 +172,9 @@
Expect.isTrue(result.stdout.isEmpty);
Expect.isTrue(result.stderr.isNotEmpty);
- return LineSplitter.split(result.stderr).toList(growable: false);
+ return await Stream.value(result.stderr as String)
+ .transform(const LineSplitter())
+ .toList();
}
const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
diff --git a/runtime/tests/vm/dart_2/use_resolve_dwarf_paths_flag_test.dart b/runtime/tests/vm/dart_2/use_resolve_dwarf_paths_flag_test.dart
index 1f9df8d..cd0ed39 100644
--- a/runtime/tests/vm/dart_2/use_resolve_dwarf_paths_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_resolve_dwarf_paths_flag_test.dart
@@ -7,7 +7,7 @@
// This test checks that --resolve-dwarf-paths outputs absolute and relative
// paths in DWARF information.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:async";
import "dart:io";
@@ -40,8 +40,7 @@
await withTempDir('dwarf-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_program.dart b/runtime/tests/vm/dart_2/use_save_debugging_info_flag_program.dart
deleted file mode 100644
index c01efdb..0000000
--- a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_program.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Test that the full stacktrace in an error object matches the stacktrace
-// handed to the catch clause.
-
-// @dart = 2.9
-
-import "package:expect/expect.dart";
-
-class C {
- // operator*(o) is missing to trigger a noSuchMethodError when a C object
- // is used in the multiplication below.
-}
-
-bar(c) => c * 4;
-foo(c) => bar(c);
-
-main() {
- var a = foo(new C());
-}
diff --git a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart b/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
index ddee6b2..db548f4 100644
--- a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
@@ -8,7 +8,7 @@
// for stripped ELF output, and that using the debugging information to look
// up stripped stack trace information matches the non-stripped version.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:io";
import "dart:math";
@@ -43,8 +43,8 @@
await withTempDir('save-debug-info-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart_2/use_strip_flag_test.dart b/runtime/tests/vm/dart_2/use_strip_flag_test.dart
index e145e86..a552ea0 100644
--- a/runtime/tests/vm/dart_2/use_strip_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_strip_flag_test.dart
@@ -8,7 +8,7 @@
// ELF and assembly output. This test is currently very weak, in that it just
// checks that the stripped version is strictly smaller than the unstripped one.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:io";
@@ -36,9 +36,8 @@
await withTempDir('strip-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- // We can just reuse the program for the use_save_debugging_info_flag test.
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/tests/vm/dart_2/use_trace_precompiler_flag_test.dart b/runtime/tests/vm/dart_2/use_trace_precompiler_flag_test.dart
index 0cb879a..4a054e8 100644
--- a/runtime/tests/vm/dart_2/use_trace_precompiler_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_trace_precompiler_flag_test.dart
@@ -7,7 +7,7 @@
// This test ensures that --trace-precompiler runs without issue and prints
// valid JSON for reasons to retain objects.
-// OtherResources=use_save_debugging_info_flag_program.dart
+// OtherResources=use_dwarf_stack_traces_flag_program.dart
import "dart:convert";
import "dart:io";
@@ -39,9 +39,8 @@
await withTempDir('trace-precompiler-flag-test', (String tempDir) async {
final cwDir = path.dirname(Platform.script.toFilePath());
- // We can just reuse the program for the use_save_debugging_info_flag test.
- final script =
- path.join(cwDir, 'use_save_debugging_info_flag_program.dart');
+ // We can just reuse the program for the use_dwarf_stack_traces test.
+ final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart');
final scriptDill = path.join(tempDir, 'flag_program.dill');
// Compile script to Kernel IR.
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index e9bc548..6e82679 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -330,7 +330,6 @@
V(Internal_writeIntoOneByteString, 3) \
V(Internal_writeIntoTwoByteString, 3) \
V(Internal_deoptimizeFunctionsOnStack, 0) \
- V(Internal_randomAddressInsideAllocateObjectStub, 0) \
V(InvocationMirror_unpackTypeArguments, 2) \
V(NoSuchMethodError_existingMethodSignature, 3) \
V(Uri_isWindowsPlatform, 0) \
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 934db51..c02b2f8 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -179,10 +179,6 @@
@pragma("vm:external-name", "Internal_deoptimizeFunctionsOnStack")
external static void deoptimizeFunctionsOnStack();
-
- // Used to verify that PC addresses in stubs can be named using DWARF info.
- @pragma("vm:external-name", "Internal_randomAddressInsideAllocateObjectStub")
- external static int randomAddressInsideAllocateObjectStub();
}
@patch