089aeedf56
Removes an unnecessary change to the names of type testing stubs that allowed name collisions to happen. Old commit message: The flag can be used when creating AOT snapshots. The resulting file can be used with package:vm/dwarf/convert.dart to convert DWARF-based stack traces to stack traces with function, file, and line number information. Currently the saved file will be an ELF file with DWARF debugging information, but this is subject to change in the future. To avoid being affected by any changes in format, read the DWARF information from the file using Dwarf.fromFile() in package:vm/dwarf/dwarf.dart. Also adds --dwarf-stack-traces to the VM global flag list, so its value at compilation will be read out of snapshots by the precompiled runtime. Fixes https://github.com/dart-lang/sdk/issues/39512, which was due to a missing compiler::target:: prefix for Instructions::HeaderSize() in BlobImageWriter::WriteText(). Exposes the information suggested in https://github.com/dart-lang/sdk/issues/39490 so that package:vm/dwarf can appropriately convert absolute PC addresses to the correct virtual address for a given DWARF line number program. Bug: https://github.com/dart-lang/sdk/issues/35851 Change-Id: I6723449dceb0b89c054a1f1e70e7acd7749baf14 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128730 Reviewed-by: Martin Kustermann <kustermann@google.com>
124 lines
3.8 KiB
Dart
124 lines
3.8 KiB
Dart
// Copyright (c) 2019, 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 "dart:async";
|
|
import "dart:convert";
|
|
import "dart:io" as io;
|
|
|
|
import 'package:args/args.dart' show ArgParser, ArgResults;
|
|
import 'package:vm/dwarf/convert.dart';
|
|
import 'package:vm/dwarf/dwarf.dart';
|
|
|
|
final ArgParser _argParser = new ArgParser(allowTrailingOptions: true)
|
|
..addOption('elf',
|
|
abbr: 'e',
|
|
help: 'Path to ELF file with debugging information',
|
|
defaultsTo: null,
|
|
valueHelp: 'FILE')
|
|
..addOption('input',
|
|
abbr: 'i',
|
|
help: 'Path to input file',
|
|
defaultsTo: null,
|
|
valueHelp: 'FILE')
|
|
..addOption('location',
|
|
abbr: 'l',
|
|
help: 'PC address to convert to a file name and line number',
|
|
defaultsTo: null,
|
|
valueHelp: 'INT')
|
|
..addOption('output',
|
|
abbr: 'o',
|
|
help: 'Path to output file',
|
|
defaultsTo: null,
|
|
valueHelp: 'FILE')
|
|
..addFlag('verbose',
|
|
abbr: 'v',
|
|
help: 'Translate all frames, not just frames for user or library code',
|
|
defaultsTo: false);
|
|
|
|
final String _usage = '''
|
|
Usage: convert_stack_traces [options]
|
|
|
|
Takes text that includes DWARF-based stack traces with PC addresses and
|
|
outputs the same text, but with the DWARF stack traces converted to stack traces
|
|
that contain function names, file names, and line numbers.
|
|
|
|
Reads from the file named by the argument to -i/--input as input, or stdin if
|
|
no input flag is given.
|
|
|
|
Outputs the converted contents to the file named by the argument to
|
|
-o/--output, or stdout if no output flag is given.
|
|
|
|
The -e/-elf option must be provided, and DWARF debugging information is
|
|
read from the file named by its argument.
|
|
|
|
When the -v/--verbose option is given, the converter translates all frames, not
|
|
just those corresponding to user or library code.
|
|
|
|
If an -l/--location option is provided, then the file and line number
|
|
information for the given location is looked up and output instead.
|
|
|
|
Options:
|
|
${_argParser.usage}
|
|
''';
|
|
|
|
const int _badUsageExitCode = 1;
|
|
|
|
Future<void> main(List<String> arguments) async {
|
|
final ArgResults options = _argParser.parse(arguments);
|
|
|
|
if ((options.rest.length > 0) || (options['elf'] == null)) {
|
|
print(_usage);
|
|
io.exitCode = _badUsageExitCode;
|
|
return;
|
|
}
|
|
|
|
int location = null;
|
|
if (options['location'] != null) {
|
|
location = int.tryParse(options['location']);
|
|
if (location == null) {
|
|
// Try adding an initial "0x", as DWARF stack traces don't normally
|
|
// include the hex marker on the PC addresses.
|
|
location = int.tryParse("0x" + options['location']);
|
|
}
|
|
if (location == null) {
|
|
print("Location could not be parsed as an int: ${options['location']}\n");
|
|
print(_usage);
|
|
io.exitCode = _badUsageExitCode;
|
|
return;
|
|
}
|
|
}
|
|
|
|
final dwarf = Dwarf.fromFile(options['elf']);
|
|
|
|
final output = options['output'] != null
|
|
? io.File(options['output']).openWrite()
|
|
: io.stdout;
|
|
final verbose = options['verbose'];
|
|
|
|
var convertedStream;
|
|
if (location != null) {
|
|
final frames = dwarf
|
|
.callInfo(location, includeInternalFrames: verbose)
|
|
?.map((CallInfo c) => c.toString());
|
|
if (frames == null) {
|
|
throw "No call information found for PC 0x${location.toRadixString(16)}";
|
|
}
|
|
convertedStream = Stream.fromIterable(frames);
|
|
} else {
|
|
final input = options['input'] != null
|
|
? io.File(options['input']).openRead()
|
|
: io.stdin;
|
|
|
|
convertedStream = input
|
|
.transform(utf8.decoder)
|
|
.transform(const LineSplitter())
|
|
.transform(
|
|
DwarfStackTraceDecoder(dwarf, includeInternalFrames: verbose));
|
|
}
|
|
|
|
await convertedStream.forEach(output.writeln);
|
|
await output.flush();
|
|
await output.close();
|
|
}
|