db2c9eeb76
TBR=johnniwinther@google.com Change-Id: I252751d8163a056784b10dcb58633c4206a849a0 Reviewed-on: https://dart-review.googlesource.com/c/82883 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Sigmund Cherem <sigmund@google.com>
87 lines
3.1 KiB
Dart
87 lines
3.1 KiB
Dart
// Copyright (c) 2018, 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:io';
|
|
import 'dart:math' show max;
|
|
import 'package:stack_trace/stack_trace.dart';
|
|
import 'package:dart2js_tools/src/trace.dart';
|
|
import 'package:dart2js_tools/src/name_decoder.dart';
|
|
import 'package:dart2js_tools/src/util.dart';
|
|
import 'package:dart2js_tools/src/trace_decoder.dart';
|
|
|
|
/// Script that deobuscates a stack-trace given in a text file.
|
|
///
|
|
/// To run this script you need 3 or more files:
|
|
///
|
|
/// * A stacktrace file
|
|
/// * The deployed .js file
|
|
/// * The corresponding .map file
|
|
///
|
|
/// There might be more than one .js/.map file if your app is divided in
|
|
/// deferred chunks.
|
|
///
|
|
/// The stack trace file contains a copy/paste of a JavaScript stack trace, of
|
|
/// this form:
|
|
///
|
|
/// at aB.a20 (main.dart.js:71969:32)
|
|
/// at aNk.goV (main.dart.js:72040:52)
|
|
/// at aNk.gfK (main.dart.js:72038:27)
|
|
/// at FE.gtn (main.dart.js:72640:24)
|
|
/// at aBZ.ghN (main.dart.js:72642:24)
|
|
/// at inheritance (main.dart.js:105334:0)
|
|
/// at FE (main.dart.js:5037:18)
|
|
///
|
|
/// If you download the stacktrace from a production service, you can keep the
|
|
/// full URL (including http://....) and this script will simply try to match
|
|
/// the name of the file at the end with a file in the current working
|
|
/// directory.
|
|
///
|
|
/// The .js file must contain a `//# sourceMappingURL=` line at the end, which
|
|
/// tells this script how to determine the name of the source-map file.
|
|
main(List<String> args) {
|
|
if (args.length != 1) {
|
|
print('usage: deobfuscate.dart <stack-trace-file>');
|
|
exit(1);
|
|
}
|
|
var sb = new StringBuffer();
|
|
try {
|
|
String obfuscatedTrace = new File(args[0]).readAsStringSync();
|
|
String error = extractErrorMessage(obfuscatedTrace);
|
|
var provider = new CachingFileProvider();
|
|
StackDeobfuscationResult result =
|
|
deobfuscateStack(obfuscatedTrace, provider);
|
|
Frame firstFrame = result.original.frames.first;
|
|
String translatedError =
|
|
translate(error, provider.mappingFor(firstFrame.uri));
|
|
if (translatedError == null) translatedError = '<no error message found>';
|
|
printPadded(translatedError, error, sb);
|
|
int longest =
|
|
result.deobfuscated.frames.fold(0, (m, f) => max(f.member.length, m));
|
|
for (var originalFrame in result.original.frames) {
|
|
var deobfuscatedFrames = result.frameMap[originalFrame];
|
|
if (deobfuscatedFrames == null) {
|
|
printPadded('no mapping', '${originalFrame.location}', sb);
|
|
} else {
|
|
for (var frame in deobfuscatedFrames) {
|
|
printPadded('${frame.member.padRight(longest)} ${frame.location}',
|
|
'${originalFrame.location}', sb);
|
|
}
|
|
}
|
|
}
|
|
} finally {
|
|
print('$sb');
|
|
}
|
|
}
|
|
|
|
final green = stdout.hasTerminal ? '\x1b[32m' : '';
|
|
final none = stdout.hasTerminal ? '\x1b[0m' : '';
|
|
|
|
printPadded(String mapping, String original, sb) {
|
|
var len = mapping.length;
|
|
var s = mapping.indexOf('\n');
|
|
if (s >= 0) len -= s + 1;
|
|
var pad = ' ' * (50 - len);
|
|
sb.writeln('$green$mapping$none$pad ... $original');
|
|
}
|