pkg:native_stack_traces - fix existing lints

And validate lints as part of test matrix

Change-Id: Ia074c56f0c7a7f9a674202667ac4729d06993302
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/216689
Auto-Submit: Kevin Moore <kevmoo@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
This commit is contained in:
Kevin Moore 2021-10-14 07:35:43 +00:00 committed by commit-bot@chromium.org
parent fbcacd7c05
commit ca00a4b27e
7 changed files with 236 additions and 195 deletions

View file

@ -2,9 +2,9 @@
// 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 'dart:async';
import 'dart:convert';
import 'dart:io' as io;
import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:path/path.dart' as path;
@ -134,7 +134,7 @@ final _usages = <String?, String>{
const int _badUsageExitCode = 1;
void errorWithUsage(String message, {String? command}) {
print("Error: $message.\n");
print('Error: $message.\n');
print(_usages[command]);
io.exitCode = _badUsageExitCode;
}
@ -179,11 +179,11 @@ void find(ArgResults options) {
void usageError(String message) => errorWithUsage(message, command: 'find');
int? tryParseIntAddress(String s) {
if (!forceHexadecimal && !s.startsWith("0x")) {
if (!forceHexadecimal && !s.startsWith('0x')) {
final decimal = int.tryParse(s);
if (decimal != null) return decimal;
}
return int.tryParse(s.startsWith("0x") ? s.substring(2) : s, radix: 16);
return int.tryParse(s.startsWith('0x') ? s.substring(2) : s, radix: 16);
}
PCOffset? convertAddress(StackTraceHeader header, String s) {
@ -204,10 +204,10 @@ void find(ArgResults options) {
}
if ((options['vm_start'] == null) != (options['isolate_start'] == null)) {
return usageError("need both VM start and isolate start");
return usageError('need both VM start and isolate start');
}
int vmStart = dwarf.vmStartAddress;
var vmStart = dwarf.vmStartAddress;
if (options['vm_start'] != null) {
final address = tryParseIntAddress(options['vm_start']);
if (address == null) {
@ -217,7 +217,7 @@ void find(ArgResults options) {
vmStart = address;
}
int isolateStart = dwarf.isolateStartAddress;
var isolateStart = dwarf.isolateStartAddress;
if (options['isolate_start'] != null) {
final address = tryParseIntAddress(options['isolate_start']);
if (address == null) {
@ -241,14 +241,14 @@ void find(ArgResults options) {
final addr = dwarf.virtualAddressOf(offset);
final frames = dwarf
.callInfoFor(addr, includeInternalFrames: verbose)
?.map((CallInfo c) => " " + c.toString());
?.map((CallInfo c) => ' ' + c.toString());
final addrString =
addr > 0 ? "0x" + addr.toRadixString(16) : addr.toString();
print("For virtual address ${addrString}:");
addr > 0 ? '0x' + addr.toRadixString(16) : addr.toString();
print('For virtual address ${addrString}:');
if (frames == null) {
print(" Invalid virtual address.");
print(' Invalid virtual address.');
} else if (frames.isEmpty) {
print(" Not a call from user or library code.");
print(' Not a call from user or library code.');
} else {
frames.forEach(print);
}
@ -280,7 +280,7 @@ Future<void> translate(ArgResults options) async {
.transform(utf8.decoder)
.transform(const LineSplitter())
.transform(DwarfStackTraceDecoder(dwarf, includeInternalFrames: verbose))
.map((s) => s + "\n")
.map((s) => s + '\n')
.transform(utf8.encoder);
await output.addStream(convertedStream);

View file

@ -3,20 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
// The section name in which the build ID is stored as a note.
const String buildIdSectionName = ".note.gnu.build-id";
const String buildIdSectionName = '.note.gnu.build-id';
// The type of a build ID note.
const int buildIdNoteType = 3;
// The name of a build ID note.
const String buildIdNoteName = "GNU";
const String buildIdNoteName = 'GNU';
// The dynamic symbol name for the VM instructions section.
const String vmSymbolName = "_kDartVmSnapshotInstructions";
const String vmSymbolName = '_kDartVmSnapshotInstructions';
// The dynamic symbol name for the VM data section.
const String vmDataSymbolName = "_kDartVmSnapshotData";
const String vmDataSymbolName = '_kDartVmSnapshotData';
// The dynamic symbol name for the isolate instructions section.
const String isolateSymbolName = "_kDartIsolateSnapshotInstructions";
const String isolateSymbolName = '_kDartIsolateSnapshotInstructions';
// The dynamic symbol name for the isolate data section.
const String isolateDataSymbolName = "_kDartIsolateSnapshotData";
const String isolateDataSymbolName = '_kDartIsolateSnapshotData';

View file

@ -2,14 +2,14 @@
// 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:math";
import 'dart:async';
import 'dart:math';
import 'constants.dart' as constants;
import "dwarf.dart";
import 'dwarf.dart';
String _stackTracePiece(CallInfo call, int depth) =>
"#${depth.toString().padRight(6)} ${call}";
'#${depth.toString().padRight(6)} ${call}';
// A pattern matching the last line of the non-symbolic stack trace header.
//
@ -45,7 +45,7 @@ class StackTraceHeader {
/// The [PCOffset] for the given absolute program counter address.
PCOffset offsetOf(int address) {
final isolateOffset = address - _isolateStart;
int vmOffset = address - _vmStart;
var vmOffset = address - _vmStart;
if (vmOffset > 0 && vmOffset == min(vmOffset, isolateOffset)) {
return PCOffset(vmOffset, InstructionsSection.vm);
} else {
@ -87,11 +87,11 @@ PCOffset? tryParseSymbolOffset(String s, [bool forceHexadecimal = false]) {
final symbolString = match.namedGroup('symbol')!;
final offsetString = match.namedGroup('offset')!;
int? offset;
if (!forceHexadecimal && !offsetString.startsWith("0x")) {
if (!forceHexadecimal && !offsetString.startsWith('0x')) {
offset = int.tryParse(offsetString);
}
if (offset == null) {
final digits = offsetString.startsWith("0x")
final digits = offsetString.startsWith('0x')
? offsetString.substring(2)
: offsetString;
offset = int.tryParse(digits, radix: 16);
@ -182,8 +182,9 @@ class DwarfStackTraceDecoder extends StreamTransformerBase<String, String> {
DwarfStackTraceDecoder(this._dwarf, {bool includeInternalFrames = false})
: _includeInternalFrames = includeInternalFrames;
@override
Stream<String> bind(Stream<String> stream) async* {
int depth = 0;
var depth = 0;
StackTraceHeader? header;
await for (final line in stream) {
final parsedHeader = _parseInstructionsLine(line);

View file

@ -13,9 +13,9 @@ import 'reader.dart';
int _initialLengthValue(Reader reader) {
final length = reader.readBytes(4);
if (length == 0xffffffff) {
throw FormatException("64-bit DWARF format detected");
throw FormatException('64-bit DWARF format detected');
} else if (length > 0xfffffff0) {
throw FormatException("Unrecognized reserved initial length value");
throw FormatException('Unrecognized reserved initial length value');
}
return length;
}
@ -33,9 +33,9 @@ const _tags = <int, _Tag>{
};
const _tagStrings = <_Tag, String>{
_Tag.compileUnit: "DW_TAG_compile_unit",
_Tag.inlinedSubroutine: "DW_TAG_inlined_subroutine",
_Tag.subprogram: "DW_TAG_subroutine",
_Tag.compileUnit: 'DW_TAG_compile_unit',
_Tag.inlinedSubroutine: 'DW_TAG_inlined_subroutine',
_Tag.subprogram: 'DW_TAG_subroutine',
};
enum _AttributeName {
@ -77,22 +77,22 @@ const _attributeNames = <int, _AttributeName>{
};
const _attributeNameStrings = <_AttributeName, String>{
_AttributeName.sibling: "DW_AT_sibling",
_AttributeName.name: "DW_AT_name",
_AttributeName.statementList: "DW_AT_stmt_list",
_AttributeName.lowProgramCounter: "DW_AT_low_pc",
_AttributeName.highProgramCounter: "DW_AT_high_pc",
_AttributeName.compilationDirectory: "DW_AT_comp_dir",
_AttributeName.inline: "DW_AT_inline",
_AttributeName.producer: "DW_AT_producer",
_AttributeName.abstractOrigin: "DW_AT_abstract_origin",
_AttributeName.artificial: "DW_AT_artificial",
_AttributeName.declarationColumn: "DW_AT_decl_column",
_AttributeName.declarationFile: "DW_AT_decl_file",
_AttributeName.declarationLine: "DW_AT_decl_line",
_AttributeName.callColumn: "DW_AT_call_column",
_AttributeName.callFile: "DW_AT_call_file",
_AttributeName.callLine: "DW_AT_call_line",
_AttributeName.sibling: 'DW_AT_sibling',
_AttributeName.name: 'DW_AT_name',
_AttributeName.statementList: 'DW_AT_stmt_list',
_AttributeName.lowProgramCounter: 'DW_AT_low_pc',
_AttributeName.highProgramCounter: 'DW_AT_high_pc',
_AttributeName.compilationDirectory: 'DW_AT_comp_dir',
_AttributeName.inline: 'DW_AT_inline',
_AttributeName.producer: 'DW_AT_producer',
_AttributeName.abstractOrigin: 'DW_AT_abstract_origin',
_AttributeName.artificial: 'DW_AT_artificial',
_AttributeName.declarationColumn: 'DW_AT_decl_column',
_AttributeName.declarationFile: 'DW_AT_decl_file',
_AttributeName.declarationLine: 'DW_AT_decl_line',
_AttributeName.callColumn: 'DW_AT_call_column',
_AttributeName.callFile: 'DW_AT_call_file',
_AttributeName.callLine: 'DW_AT_call_line',
};
enum _AttributeForm {
@ -114,12 +114,12 @@ const _attributeForms = <int, _AttributeForm>{
};
const _attributeFormStrings = <_AttributeForm, String>{
_AttributeForm.address: "DW_FORM_addr",
_AttributeForm.string: "DW_FORM_string",
_AttributeForm.flag: "DW_FORM_flag",
_AttributeForm.constant: "DW_FORM_udata",
_AttributeForm.reference4: "DW_FORM_ref4",
_AttributeForm.sectionOffset: "DW_FORM_sec_offset",
_AttributeForm.address: 'DW_FORM_addr',
_AttributeForm.string: 'DW_FORM_string',
_AttributeForm.flag: 'DW_FORM_flag',
_AttributeForm.constant: 'DW_FORM_udata',
_AttributeForm.reference4: 'DW_FORM_ref4',
_AttributeForm.sectionOffset: 'DW_FORM_sec_offset',
};
class _Attribute {
@ -133,10 +133,10 @@ class _Attribute {
final formInt = reader.readLEB128EncodedInteger();
if (nameInt == 0 && formInt == 0) return null;
if (!_attributeNames.containsKey(nameInt)) {
throw FormatException("Unexpected DW_AT value 0x${paddedHex(nameInt)}");
throw FormatException('Unexpected DW_AT value 0x${paddedHex(nameInt)}');
}
if (!_attributeForms.containsKey(formInt)) {
throw FormatException("Unexpected DW_FORM value 0x${paddedHex(formInt)}");
throw FormatException('Unexpected DW_FORM value 0x${paddedHex(formInt)}');
}
return _Attribute._(_attributeNames[nameInt]!, _attributeForms[formInt]!);
}
@ -173,7 +173,7 @@ class _Attribute {
case _AttributeForm.reference4:
final intValue = value as int;
final unresolvedValue = paddedHex(intValue, 4);
final name = unit?.nameOfOrigin(intValue) ?? "<unresolved>";
final name = unit?.nameOfOrigin(intValue) ?? '<unresolved>';
return '0x${unresolvedValue} (origin: ${name})';
}
}
@ -196,13 +196,13 @@ class _Abbreviation {
if (code == 0) return null;
final tagInt = reader.readLEB128EncodedInteger();
if (!_tags.containsKey(tagInt)) {
throw FormatException("Unexpected DW_TAG value 0x${paddedHex(tagInt)}");
throw FormatException('Unexpected DW_TAG value 0x${paddedHex(tagInt)}');
}
final tag = _tags[tagInt]!;
final childrenByte = reader.readByte();
if (childrenByte != _DW_CHILDREN_no && childrenByte != _DW_CHILDREN_yes) {
throw FormatException("Expected DW_CHILDREN_no or DW_CHILDREN_yes: "
"${childrenByte}");
throw FormatException('Expected DW_CHILDREN_no or DW_CHILDREN_yes: '
'${childrenByte}');
}
final children = childrenByte == _DW_CHILDREN_yes;
final attributes = reader.readRepeated(_Attribute.fromReader).toList();
@ -249,7 +249,9 @@ class _AbbreviationsTable {
}
void writeToStringBuffer(StringBuffer buffer) {
buffer..writeln('Abbreviations table:')..writeln();
buffer
..writeln('Abbreviations table:')
..writeln();
_abbreviations.forEach((key, abbreviation) {
buffer
..write(' ')
@ -283,7 +285,7 @@ class DebugInformationEntry {
// DIEs with an abbreviation table index of 0 are list end markers.
if (code == 0) return null;
if (!header.abbreviations.containsKey(code)) {
throw FormatException("Unknown abbreviation code 0x${paddedHex(code)}");
throw FormatException('Unknown abbreviation code 0x${paddedHex(code)}');
}
final abbreviation = header.abbreviations[code]!;
final attributes = <_Attribute, Object>{};
@ -396,7 +398,7 @@ class DebugInformationEntry {
..writeln('):');
final sortedChildren = children.entries.toList()
..sort((kv1, kv2) => Comparable.compare(kv1.key, kv2.key));
for (int i = 0; i < sortedChildren.length; i++) {
for (var i = 0; i < sortedChildren.length; i++) {
final offset = sortedChildren[i].key;
final child = sortedChildren[i].value;
buffer
@ -411,6 +413,7 @@ class DebugInformationEntry {
}
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -435,13 +438,13 @@ class CompilationUnitHeader {
if (size == 0) return null;
final version = reader.readBytes(2);
if (version != 2) {
throw FormatException("Expected DWARF version 2, got $version");
throw FormatException('Expected DWARF version 2, got $version');
}
final abbreviationsOffset = reader.readBytes(4);
final abbreviationsTable = abbreviationsTables[abbreviationsOffset];
if (abbreviationsTable == null) {
throw FormatException("No abbreviation table found for offset "
"0x${paddedHex(abbreviationsOffset, 4)}");
throw FormatException('No abbreviation table found for offset '
'0x${paddedHex(abbreviationsOffset, 4)}');
}
final addressSize = reader.readByte();
return CompilationUnitHeader._(
@ -518,7 +521,7 @@ class CompilationUnit {
final origin = referenceTable[offset];
if (origin == null) {
throw ArgumentError(
"${paddedHex(offset)} is not the offset of an abbreviated unit");
'${paddedHex(offset)} is not the offset of an abbreviated unit');
}
return origin[_AttributeName.name] as String;
}
@ -573,6 +576,7 @@ class DebugInfo {
}
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -591,7 +595,7 @@ class FileEntry {
static FileEntry? fromReader(Reader reader) {
final name = reader.readNullTerminatedString();
// An empty null-terminated string marks the table end.
if (name == "") return null;
if (name == '') return null;
final directoryIndex = reader.readLEB128EncodedInteger();
final lastModified = reader.readLEB128EncodedInteger();
final size = reader.readLEB128EncodedInteger();
@ -599,10 +603,10 @@ class FileEntry {
}
@override
String toString() => "File name: $name\n"
" Directory index: $directoryIndex\n"
" Last modified: $lastModified\n"
" Size: $size\n";
String toString() => 'File name: $name\n'
' Directory index: $directoryIndex\n'
' Last modified: $lastModified\n'
' Size: $size\n';
}
class FileInfo {
@ -613,7 +617,7 @@ class FileInfo {
static FileInfo fromReader(Reader reader) {
final offsetFiles = reader.readRepeated(FileEntry.fromReader).toList();
final files = <int, FileEntry>{};
for (int i = 0; i < offsetFiles.length; i++) {
for (var i = 0; i < offsetFiles.length; i++) {
// File entries are one-based, not zero-based.
files[i + 1] = offsetFiles[i];
}
@ -625,15 +629,15 @@ class FileInfo {
void writeToStringBuffer(StringBuffer buffer) {
if (_files.isEmpty) {
buffer.writeln("No file information.");
buffer.writeln('No file information.');
return;
}
final indexHeader = "Entry";
final dirIndexHeader = "Dir";
final modifiedHeader = "Time";
final sizeHeader = "Size";
final nameHeader = "Name";
final indexHeader = 'Entry';
final dirIndexHeader = 'Dir';
final modifiedHeader = 'Time';
final sizeHeader = 'Size';
final nameHeader = 'Name';
final indexStrings = _files
.map((int i, FileEntry f) => MapEntry<int, String>(i, i.toString()));
@ -653,27 +657,39 @@ class FileInfo {
final maxSizeLength = sizeStrings.values
.fold(sizeHeader.length, (int acc, String s) => max(acc, s.length));
buffer.writeln("File information:");
buffer.writeln('File information:');
buffer..write(" ")..write(indexHeader.padRight(maxIndexLength));
buffer..write(" ")..write(dirIndexHeader.padRight(maxDirIndexLength));
buffer..write(" ")..write(modifiedHeader.padRight(maxModifiedLength));
buffer..write(" ")..write(sizeHeader.padRight(maxSizeLength));
buffer
..write(" ")
..write(' ')
..write(indexHeader.padRight(maxIndexLength));
buffer
..write(' ')
..write(dirIndexHeader.padRight(maxDirIndexLength));
buffer
..write(' ')
..write(modifiedHeader.padRight(maxModifiedLength));
buffer
..write(' ')
..write(sizeHeader.padRight(maxSizeLength));
buffer
..write(' ')
..writeln(nameHeader);
for (final index in _files.keys) {
buffer..write(" ")..write(indexStrings[index]!.padRight(maxIndexLength));
buffer
..write(" ")
..write(' ')
..write(indexStrings[index]!.padRight(maxIndexLength));
buffer
..write(' ')
..write(dirIndexStrings[index]!.padRight(maxDirIndexLength));
buffer
..write(" ")
..write(' ')
..write(modifiedStrings[index]!.padRight(maxModifiedLength));
buffer..write(" ")..write(sizeStrings[index]!.padRight(maxSizeLength));
buffer
..write(" ")
..write(' ')
..write(sizeStrings[index]!.padRight(maxSizeLength));
buffer
..write(' ')
..writeln(_files[index]!.name);
}
}
@ -723,11 +739,12 @@ class LineNumberState {
return clone;
}
String toString() => "Current line number state machine registers:\n"
" Address: ${paddedHex(address)}\n"
" File index: $fileIndex\n"
" Line number: $line\n"
" Column number: $column\n"
@override
String toString() => 'Current line number state machine registers:\n'
' Address: ${paddedHex(address)}\n'
' File index: $fileIndex\n'
' Line number: $line\n'
' Column number: $column\n'
" Is ${isStatement ? "" : "not "}a statement.\n"
" Is ${basicBlock ? "" : "not "}at the beginning of a basic block.\n"
" Is ${endSequence ? "" : "not "}just after the end of a sequence.";
@ -772,7 +789,7 @@ class LineNumberProgramHeader {
final isStmtByte = reader.readByte();
if (isStmtByte < 0 || isStmtByte > 1) {
throw FormatException(
"Unexpected value for default_is_stmt: ${isStmtByte}");
'Unexpected value for default_is_stmt: ${isStmtByte}');
}
final defaultIsStatement = isStmtByte == 1;
final lineBase = reader.readByte(signed: true);
@ -780,24 +797,24 @@ class LineNumberProgramHeader {
final opcodeBase = reader.readByte();
final standardOpcodeLengths = <int, int>{};
// Standard opcode numbering starts at 1.
for (int i = 1; i < opcodeBase; i++) {
for (var i = 1; i < opcodeBase; i++) {
standardOpcodeLengths[i] = reader.readLEB128EncodedInteger();
}
final includeDirectories = <String>[];
while (!reader.done) {
final directory = reader.readNullTerminatedString();
if (directory == "") break;
if (directory == '') break;
includeDirectories.add(directory);
}
if (reader.done) {
throw FormatException("Unterminated directory entry");
throw FormatException('Unterminated directory entry');
}
final filesInfo = FileInfo.fromReader(reader);
// Header length doesn't include the 2-byte version or 4-byte length fields.
if (reader.offset != headerStart + headerLength) {
throw FormatException("At offset ${reader.offset} after header, "
"expected to be at offset ${headerStart + headerLength}");
throw FormatException('At offset ${reader.offset} after header, '
'expected to be at offset ${headerStart + headerLength}');
}
return LineNumberProgramHeader._(
@ -833,7 +850,7 @@ class LineNumberProgramHeader {
..write(' Opcode base: ')
..writeln(opcodeBase)
..writeln('Standard opcode lengths:');
for (int i = 1; i < opcodeBase; i++) {
for (var i = 1; i < opcodeBase; i++) {
buffer
..write(' Opcode ')
..write(i)
@ -876,7 +893,7 @@ class LineNumberProgram {
if (header == null) return null;
final calculatedMatrix = _readOpcodes(reader, header).toList();
if (calculatedMatrix.isEmpty) {
throw FormatException("No line number information generated by program");
throw FormatException('No line number information generated by program');
}
return LineNumberProgram._(header, calculatedMatrix);
}
@ -903,7 +920,7 @@ class LineNumberProgram {
final subOpcode = reader.readByte();
switch (subOpcode) {
case 0:
throw FormatException("Attempted to execute extended opcode 0");
throw FormatException('Attempted to execute extended opcode 0');
case 1: // DW_LNE_end_sequence
state.endSequence = true;
yield state.clone();
@ -918,10 +935,10 @@ class LineNumberProgram {
break;
case 3: // DW_LNE_define_file
throw FormatException(
"DW_LNE_define_file instruction not handled");
'DW_LNE_define_file instruction not handled');
default:
throw FormatException(
"Extended opcode ${subOpcode} not in DWARF 2");
'Extended opcode ${subOpcode} not in DWARF 2');
}
break;
case 1: // DW_LNS_copy
@ -954,7 +971,7 @@ class LineNumberProgram {
state.address += reader.readBytes(2);
break;
default:
throw FormatException("Standard opcode ${opcode} not in DWARF 2");
throw FormatException('Standard opcode ${opcode} not in DWARF 2');
}
}
}
@ -1003,12 +1020,13 @@ class LineNumberProgram {
void writeToStringBuffer(StringBuffer buffer) {
header.writeToStringBuffer(buffer);
buffer.writeln("Results of line number program:");
buffer.writeln('Results of line number program:');
for (final state in calculatedMatrix) {
buffer..writeln(state);
}
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -1040,6 +1058,7 @@ class LineNumberInfo {
});
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -1090,7 +1109,7 @@ class DartCallInfo extends CallInfo {
@override
int get hashCode {
int hash = 0;
var hash = 0;
hash = _hashCombine(hash, inlined.hashCode);
hash = _hashCombine(hash, internal.hashCode);
hash = _hashCombine(hash, function.hashCode);
@ -1114,11 +1133,18 @@ class DartCallInfo extends CallInfo {
}
void writeToStringBuffer(StringBuffer buffer) {
buffer..write(function)..write(' (')..write(filename);
buffer
..write(function)
..write(' (')
..write(filename);
if (line > 0) {
buffer..write(':')..write(line);
buffer
..write(':')
..write(line);
if (column > 0) {
buffer..write(':')..write(column);
buffer
..write(':')
..write(column);
}
}
buffer.write(')');
@ -1152,7 +1178,7 @@ class StubCallInfo extends CallInfo {
}
@override
String toString() => "${name}+0x${offset.toRadixString(16)}";
String toString() => '${name}+0x${offset.toRadixString(16)}';
}
/// The instructions section in which a program counter address is located.
@ -1235,23 +1261,23 @@ class Dwarf {
Dwarf.fromReader(Reader.fromFile(path));
static Dwarf _loadSectionsFromElf(Reader reader, Elf elf) {
final abbrevSection = elf.namedSections(".debug_abbrev").single;
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 lineNumberSection = elf.namedSections('.debug_line').single;
final lineNumberInfo =
LineNumberInfo.fromReader(lineNumberSection.refocusedCopy(reader));
final infoSection = elf.namedSections(".debug_info").single;
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}");
'Expected a dynamic symbol with name ${constants.vmSymbolName}');
}
final vmStartAddress = vmStartSymbol.value;
@ -1259,7 +1285,7 @@ class Dwarf {
elf.dynamicSymbolFor(constants.isolateSymbolName);
if (isolateStartSymbol == null) {
throw FormatException(
"Expected a dynamic symbol with name ${constants.isolateSymbolName}");
'Expected a dynamic symbol with name ${constants.isolateSymbolName}');
}
final isolateStartAddress = isolateStartSymbol.value;
@ -1316,7 +1342,7 @@ class Dwarf {
case InstructionsSection.isolate:
return pcOffset.offset + isolateStartAddress;
default:
throw "Unexpected value for instructions section";
throw 'Unexpected value for instructions section';
}
}
@ -1327,7 +1353,10 @@ class Dwarf {
..writeln('----------------------------------------')
..writeln();
_abbreviationsTables.forEach((offset, table) {
buffer..write('(Offset ')..write(paddedHex(offset, 4))..write(') ');
buffer
..write('(Offset ')
..write(paddedHex(offset, 4))
..write(') ');
table.writeToStringBuffer(buffer);
});
buffer

View file

@ -39,11 +39,11 @@ int _readElfWord(Reader reader) {
int _readElfXword(Reader reader) {
switch (reader.wordSize) {
case 4:
throw "Internal reader error: reading Elf64_Xword in 32-bit ELF file";
throw 'Internal reader error: reading Elf64_Xword in 32-bit ELF file';
case 8:
return _readElfBytes(reader, 8, 8);
default:
throw "Unsupported word size ${reader.wordSize}";
throw 'Unsupported word size ${reader.wordSize}';
}
}
@ -61,7 +61,7 @@ int _readElfNative(Reader reader) {
case 8:
return _readElfXword(reader);
default:
throw "Unsupported word size ${reader.wordSize}";
throw 'Unsupported word size ${reader.wordSize}';
}
}
@ -113,14 +113,14 @@ class ElfHeader {
wordSize = 8;
break;
default:
throw FormatException("Unexpected e_ident[EI_CLASS] value");
throw FormatException('Unexpected e_ident[EI_CLASS] value');
}
final calculatedHeaderSize = 0x18 + 3 * wordSize + 0x10;
if (fileSize < calculatedHeaderSize) {
throw FormatException("ELF file too small for header: "
"file size ${fileSize} < "
"calculated header size $calculatedHeaderSize");
throw FormatException('ELF file too small for header: '
'file size ${fileSize} < '
'calculated header size $calculatedHeaderSize');
}
Endian endian;
@ -132,11 +132,11 @@ class ElfHeader {
endian = Endian.big;
break;
default:
throw FormatException("Unexpected e_indent[EI_DATA] value");
throw FormatException('Unexpected e_indent[EI_DATA] value');
}
if (reader.readByte() != 0x01) {
throw FormatException("Unexpected e_ident[EI_VERSION] value");
throw FormatException('Unexpected e_ident[EI_VERSION] value');
}
// After this point, we need the reader to be correctly set up re: word
@ -147,7 +147,7 @@ class ElfHeader {
// Skip rest of e_ident/e_type/e_machine, i.e. move to e_version.
reader.seek(0x14, absolute: true);
if (_readElfWord(reader) != 0x01) {
throw FormatException("Unexpected e_version value");
throw FormatException('Unexpected e_version value');
}
final entry = _readElfAddress(reader);
@ -167,25 +167,25 @@ class ElfHeader {
final sectionHeaderStringsIndex = _readElfHalf(reader);
if (reader.offset != headerSize) {
throw FormatException("Only read ${reader.offset} bytes, not the "
"full header size ${headerSize}");
throw FormatException('Only read ${reader.offset} bytes, not the '
'full header size ${headerSize}');
}
if (headerSize != calculatedHeaderSize) {
throw FormatException("Stored ELF header size ${headerSize} != "
"calculated ELF header size $calculatedHeaderSize");
throw FormatException('Stored ELF header size ${headerSize} != '
'calculated ELF header size $calculatedHeaderSize');
}
if (fileSize < programHeaderOffset) {
throw FormatException("File is truncated before program header");
throw FormatException('File is truncated before program header');
}
if (fileSize < programHeaderOffset + programHeaderSize) {
throw FormatException("File is truncated within the program header");
throw FormatException('File is truncated within the program header');
}
if (fileSize < sectionHeaderOffset) {
throw FormatException("File is truncated before section header");
throw FormatException('File is truncated before section header');
}
if (fileSize < sectionHeaderOffset + sectionHeaderSize) {
throw FormatException("File is truncated within the section header");
throw FormatException('File is truncated within the section header');
}
return ElfHeader._(
@ -207,7 +207,7 @@ class ElfHeader {
int get sectionHeaderSize => sectionHeaderCount * sectionHeaderEntrySize;
// Constants used within the ELF specification.
static const _ELFMAG = "\x7fELF";
static const _ELFMAG = '\x7fELF';
static const _ELFCLASS32 = 0x01;
static const _ELFCLASS64 = 0x02;
static const _ELFDATA2LSB = 0x01;
@ -278,7 +278,7 @@ class ProgramHeaderEntry {
this.paddr, this.filesz, this.memsz, this.align, this.wordSize);
static ProgramHeaderEntry fromReader(Reader reader) {
int wordSize = reader.wordSize;
var wordSize = reader.wordSize;
assert(wordSize == 4 || wordSize == 8);
final type = _readElfWord(reader);
late int flags;
@ -299,14 +299,14 @@ class ProgramHeaderEntry {
}
static const _typeStrings = <int, String>{
_PT_NULL: "PT_NULL",
_PT_LOAD: "PT_LOAD",
_PT_DYNAMIC: "PT_DYNAMIC",
_PT_PHDR: "PT_PHDR",
_PT_NULL: 'PT_NULL',
_PT_LOAD: 'PT_LOAD',
_PT_DYNAMIC: 'PT_DYNAMIC',
_PT_PHDR: 'PT_PHDR',
};
static String _typeToString(int type) =>
_typeStrings[type] ?? "unknown (${paddedHex(type, 4)})";
_typeStrings[type] ?? 'unknown (${paddedHex(type, 4)})';
void writeToStringBuffer(StringBuffer buffer) {
buffer
@ -328,6 +328,7 @@ class ProgramHeaderEntry {
..write(paddedHex(align, wordSize));
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -364,10 +365,11 @@ class ProgramHeader {
void writeToStringBuffer(StringBuffer buffer) {
for (var i = 0; i < length; i++) {
if (i != 0)
if (i != 0) {
buffer
..writeln()
..writeln();
}
buffer
..write('Entry ')
..write(i)
@ -376,6 +378,7 @@ class ProgramHeader {
}
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -453,19 +456,19 @@ class SectionHeaderEntry {
}
static const _typeStrings = <int, String>{
_SHT_NULL: "SHT_NULL",
_SHT_PROGBITS: "SHT_PROGBITS",
_SHT_SYMTAB: "SHT_SYMTAB",
_SHT_STRTAB: "SHT_STRTAB",
_SHT_HASH: "SHT_HASH",
_SHT_DYNAMIC: "SHT_DYNAMIC",
_SHT_NOTE: "SHT_NOTE",
_SHT_NOBITS: "SHT_NOBITS",
_SHT_DYNSYM: "SHT_DYNSYM",
_SHT_NULL: 'SHT_NULL',
_SHT_PROGBITS: 'SHT_PROGBITS',
_SHT_SYMTAB: 'SHT_SYMTAB',
_SHT_STRTAB: 'SHT_STRTAB',
_SHT_HASH: 'SHT_HASH',
_SHT_DYNAMIC: 'SHT_DYNAMIC',
_SHT_NOTE: 'SHT_NOTE',
_SHT_NOBITS: 'SHT_NOBITS',
_SHT_DYNSYM: 'SHT_DYNSYM',
};
static String _typeToString(int type) =>
_typeStrings[type] ?? "unknown (${paddedHex(type, 4)})";
_typeStrings[type] ?? 'unknown (${paddedHex(type, 4)})';
void writeToStringBuffer(StringBuffer buffer) {
buffer.write('Name: ');
@ -496,6 +499,7 @@ class SectionHeaderEntry {
..write(entrySize);
}
@override
String toString() {
final buffer = StringBuffer();
writeToStringBuffer(buffer);
@ -521,10 +525,11 @@ class SectionHeader {
void writeToStringBuffer(StringBuffer buffer) {
for (var i = 0; i < entries.length; i++) {
if (i != 0)
if (i != 0) {
buffer
..writeln()
..writeln();
}
buffer
..write('Entry ')
..write(i)
@ -620,6 +625,7 @@ class Note extends Section {
return Note._(entry, type, name, description);
}
@override
void writeToStringBuffer(StringBuffer buffer) {
buffer
..write('Section "')
@ -669,9 +675,9 @@ class StringTable extends Section {
..writeln('" is a string table:');
for (var key in _entries.keys) {
buffer
..write(" ")
..write(' ')
..write(key)
..write(" => ")
..write(' => ')
..writeln(_entries[key]);
}
}
@ -734,7 +740,7 @@ class Symbol {
void _cacheNameFromStringTable(StringTable table) {
final nameFromTable = table[nameIndex];
if (nameFromTable == null) {
throw FormatException("Index $nameIndex not found in string table");
throw FormatException('Index $nameIndex not found in string table');
}
name = nameFromTable;
}
@ -770,11 +776,11 @@ class Symbol {
break;
}
buffer
..write(" symbol that points to ")
..write(' symbol that points to ')
..write(size)
..write(" bytes at location 0x")
..write(' bytes at location 0x')
..write(paddedHex(value, _wordSize))
..write(" in section ")
..write(' in section ')
..write(sectionIndex);
}
@ -821,7 +827,7 @@ class SymbolTable extends Section {
..write(headerEntry.name)
..writeln('" is a symbol table:');
for (var symbol in _entries) {
buffer.write(" ");
buffer.write(' ');
symbol.writeToStringBuffer(buffer);
buffer.writeln();
}
@ -922,7 +928,7 @@ class DynamicTable extends Section {
}
} else {
buffer
..write("Unknown tag ")
..write('Unknown tag ')
..write(kv.key)
..write(' => ')
..writeln(kv.value);
@ -975,7 +981,7 @@ class Elf {
///
/// Returns -1 if there is no dynamic symbol that matches [name].
Symbol? dynamicSymbolFor(String name) {
for (final section in namedSections(".dynsym")) {
for (final section in namedSections('.dynsym')) {
final dynsym = section as SymbolTable;
if (dynsym.containsKey(name)) return dynsym[name];
}
@ -1026,7 +1032,7 @@ class Elf {
// header entries.
if (header.sectionHeaderStringsIndex < 0 ||
header.sectionHeaderStringsIndex >= sectionHeader.entries.length) {
throw FormatException("Section header string table index invalid");
throw FormatException('Section header string table index invalid');
}
final sectionHeaderStringTableEntry =
sectionHeader.entries[header.sectionHeaderStringsIndex];
@ -1034,13 +1040,13 @@ class Elf {
sections[sectionHeaderStringTableEntry] as StringTable?;
if (sectionHeaderStringTable == null) {
throw FormatException(
"No section for entry ${sectionHeaderStringTableEntry}");
'No section for entry ${sectionHeaderStringTableEntry}');
}
final sectionsByName = <String, Set<Section>>{};
for (final entry in sectionHeader.entries) {
final section = sections[entry];
if (section == null) {
throw FormatException("No section found for entry ${entry}");
throw FormatException('No section found for entry ${entry}');
}
entry.setName(sectionHeaderStringTable);
sectionsByName.putIfAbsent(entry.name, () => {}).add(section);
@ -1062,7 +1068,7 @@ class Elf {
final stringTable = stringTableMap[entry];
if (stringTable == null) {
throw FormatException(
"String table not found at section header entry ${link}");
'String table not found at section header entry ${link}');
}
symbolTable._cacheNames(stringTable);
}
@ -1115,7 +1121,7 @@ class Elf {
@override
String toString() {
StringBuffer buffer = StringBuffer();
var buffer = StringBuffer();
writeToStringBuffer(buffer);
return buffer.toString();
}

View file

@ -20,9 +20,9 @@ class Reader {
int _offset = 0;
Endian get endian => _endian as Endian;
void set endian(Endian value) => _endian = value;
set endian(Endian value) => _endian = value;
int get wordSize => _wordSize as int;
void set wordSize(int value) => _wordSize = value;
set wordSize(int value) => _wordSize = value;
/// Unless provided, [wordSize] and [endian] are initialized to values that
/// ensure no reads are made that depend on their value (e.g., readBytes).
@ -58,8 +58,8 @@ class Reader {
int readBytes(int size, {bool signed = false}) {
if (_offset + size > length) {
throw ArgumentError("attempt to read ${size} bytes with only "
"${length - _offset} bytes remaining in the reader");
throw ArgumentError('attempt to read ${size} bytes with only '
'${length - _offset} bytes remaining in the reader');
}
final start = _offset;
_offset += size;
@ -80,7 +80,7 @@ class Reader {
: bdata.getUint64(start, endian);
default:
_offset -= size;
throw ArgumentError("invalid request to read $size bytes");
throw ArgumentError('invalid request to read $size bytes');
}
}
@ -88,7 +88,7 @@ class Reader {
int readWord() => readBytes(wordSize);
String readNullTerminatedString() {
final start = bdata.offsetInBytes + _offset;
for (int i = 0; _offset + i < bdata.lengthInBytes; i++) {
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));
@ -152,47 +152,51 @@ class Reader {
startOffset = max(startOffset, lowerWindow);
endOffset = min(endOffset, upperWindow);
}
for (int i = startOffset; i < endOffset; i += bytesPerLine) {
buffer..write("0x")..write(paddedHex(i, 8))..write(" ");
for (int j = 0; j < bytesPerLine && i + j < endOffset; j++) {
for (var i = startOffset; i < endOffset; i += bytesPerLine) {
buffer
..write('0x')
..write(paddedHex(i, 8))
..write(' ');
for (var j = 0; j < bytesPerLine && i + j < endOffset; j++) {
var byte = baseData.getUint8(i + j);
buffer
..write(i + j == currentOffset ? "|" : " ")
..write(i + j == currentOffset ? '|' : ' ')
..write(paddedHex(byte, 1));
}
buffer.writeln();
}
}
@override
String toString() {
final buffer = StringBuffer();
buffer
..write("Word size: ")
..write('Word size: ')
..write(_wordSize)
..writeln();
buffer
..write("Endianness: ")
..write('Endianness: ')
..write(_endian)
..writeln();
buffer
..write("Start: 0x")
..write('Start: 0x')
..write(paddedHex(start, _wordSize ?? 0))
..write(" (")
..write(' (')
..write(start)
..writeln(")");
..writeln(')');
buffer
..write("Offset: 0x")
..write('Offset: 0x')
..write(paddedHex(offset, _wordSize ?? 0))
..write(" (")
..write(' (')
..write(offset)
..writeln(")");
..writeln(')');
buffer
..write("Length: 0x")
..write('Length: 0x')
..write(paddedHex(length, _wordSize ?? 0))
..write(" (")
..write(' (')
..write(length)
..writeln(")");
buffer..writeln("Bytes around current position:");
..writeln(')');
buffer..writeln('Bytes around current position:');
writeCurrentReaderPosition(buffer, maxSize: 256);
return buffer.toString();
}

View file

@ -3329,6 +3329,7 @@
"script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
"analyze",
"--fatal-infos",
"pkg/native_stack_traces"
]
},