// 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:math';

import 'constants.dart' as constants;
import 'dwarf.dart';

String _stackTracePiece(CallInfo call, int depth) =>
    '#${depth.toString().padRight(6)} $call';

// The initial header line in a non-symbolic stack trace.
const _headerStartLine =
    '*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***';

// A pattern matching the os/arch line of the non-symbolic stack trace header.
//
// This RegExp has been adjusted to parse the header line found in
// non-symbolic stack traces and the modified version in signal handler stack
// traces.
final _osArchLineRE = RegExp(r'os(?:=|: )(\S+?),? '
    r'arch(?:=|: )(\S+?),? comp(?:=|: )(yes|no),? sim(?:=|: )(yes|no)');

// A pattern matching a build ID in the non-symbolic stack trace header.
//
// This RegExp has been adjusted to parse the header line found in
// non-symbolic stack traces and the modified version in signal handler stack
// traces.
const _buildIdREString = r"build_id(?:=|: )'([\da-f]+)'";
final _buildIdRE = RegExp(_buildIdREString);

// A pattern matching a loading unit in the non-symbolic stack trace header.
//
// This RegExp has been adjusted to parse the header line found in
// non-symbolic stack traces and the modified version in signal handler stack
// traces.
final _loadingUnitLineRE = RegExp(r'loading_unit(?:=|: )([\d]+),? (?:' +
    _buildIdREString +
    r',? )?dso_base(?:=|: )([\da-f]+),? instructions(?:=|: )([\da-f]+)');

// A pattern matching the isolate DSO base in the non-symbolic stack trace
// header.
//
// This RegExp has been adjusted to parse the header line found in
// non-symbolic stack traces and the modified version in signal handler stack
// traces.
final _isolateDsoBaseLineRE = RegExp(r'isolate_dso_base(?:=|: )([\da-f]+)');

// A pattern matching the last line of the non-symbolic stack trace header.
//
// This RegExp has been adjusted to parse the header line found in
// non-symbolic stack traces and the modified version in signal handler stack
// traces.
final _instructionsLineRE = RegExp(r'isolate_instructions(?:=|: )([\da-f]+),? '
    r'vm_instructions(?:=|: )([\da-f]+)');

/// Information for a loading unit.
class LoadingUnit {
  /// The id of the loading unit.
  final int id;

  /// The base address at which the loading unit was loaded.
  final int dsoBase;

  /// The address at which the loading unit instructions were loaded.
  final int start;

  /// The build ID of the loading unit, when available.
  final String? buildId;

  LoadingUnit(this.id, this.dsoBase, this.start, {this.buildId});

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('LoadingUnit(')
      ..write(id)
      ..write(', start: ')
      ..write(start.toRadixString(16))
      ..write(', dso_base: ')
      ..write(dsoBase.toRadixString(16));
    if (buildId != null) {
      buffer
        ..write(", buildId: '")
        ..write(buildId)
        ..write("'");
    }
    buffer.write(")");
  }

  @override
  String toString() {
    final b = StringBuffer();
    writeToStringBuffer(b);
    return b.toString();
  }
}

/// Header information for a non-symbolic Dart stack trace.
class StackTraceHeader {
  String? _os;
  String? _arch;
  bool? _compressed;
  bool? _simulated;
  String? _buildId;
  Map<int, LoadingUnit>? _units;
  int? _isolateStart;
  int? _vmStart;
  int? _isolateDsoBase;

  String? get os => _os;
  String? get architecture => _arch;
  String? get buildId => _buildId;
  Map<int, LoadingUnit>? get units => _units;
  bool? get compressedPointers => _compressed;
  bool? get usingSimulator => _simulated;
  int? get vmStart => _vmStart;
  int? get isolateStart => _isolateStart;
  int? get isolateDsoBase => _isolateDsoBase;

  static StackTraceHeader fromStarts(int isolateStart, int? vmStart,
          {String? architecture}) =>
      StackTraceHeader()
        .._isolateStart = isolateStart
        .._vmStart = vmStart
        .._arch = architecture;

  static StackTraceHeader fromLines(List<String> lines, {bool lossy = false}) {
    final result = StackTraceHeader();
    for (final line in lines) {
      result.tryParseHeaderLine(line, lossy: lossy);
    }
    return result;
  }

  /// Try and parse the given line as one of the recognized lines in the
  /// header of a non-symbolic stack trace.
  ///
  /// If [lossy] is true, then the parser assumes that some header lines may
  /// have been lost (e.g., due to log truncation) and recreates missing parts
  /// of the header from other parsed parts if possible.
  ///
  /// Returns whether the line was recognized and parsed successfully.
  bool tryParseHeaderLine(String line, {bool lossy = false}) {
    if (line.contains(_headerStartLine)) {
      // This is the start of a new non-symbolic stack trace, so reset all the
      // stored information to be parsed anew.
      _os = null;
      _arch = null;
      _compressed = null;
      _simulated = null;
      _buildId = null;
      _isolateStart = null;
      _isolateDsoBase = null;
      _vmStart = null;
      _units = null;
      return true;
    }
    RegExpMatch? match;
    match = _osArchLineRE.firstMatch(line);
    if (match != null) {
      _os = match[1]!;
      _arch = match[2]!;
      _compressed = match[3]! == "yes";
      _simulated = match[4]! == "yes";
      if (lossy) {
        // Reset all stored information that is parsed after this point,
        // just in case we've missed earlier lines in this header.
        _buildId = null;
        _isolateStart = null;
        _isolateDsoBase = null;
        _vmStart = null;
        _units = null;
      }
      return true;
    }
    // Have to check for loading units first because they can include a
    // build ID, so the build ID RegExp matches them as well.
    match = _loadingUnitLineRE.firstMatch(line);
    if (match != null) {
      _units ??= <int, LoadingUnit>{};
      final id = int.parse(match[1]!);
      final buildId = match[2];
      final dsoBase = int.parse(match[3]!, radix: 16);
      final start = int.parse(match[4]!, radix: 16);
      _units![id] = LoadingUnit(id, dsoBase, start, buildId: buildId);
      if (lossy) {
        // Reset all stored information that is parsed after this point,
        // just in case we've missed earlier lines in this header.
        _isolateStart = null;
        _isolateDsoBase = null;
        _vmStart = null;
      }
      return true;
    }
    match = _buildIdRE.firstMatch(line);
    if (match != null) {
      _buildId = match[1]!;
      if (lossy) {
        // Reset all stored information that is parsed after this point,
        // just in case we've missed earlier lines in this header.
        _isolateStart = null;
        _isolateDsoBase = null;
        _vmStart = null;
        _units = null;
      }
      return true;
    }
    match = _isolateDsoBaseLineRE.firstMatch(line);
    if (match != null) {
      _isolateDsoBase = int.parse(match[1]!, radix: 16);
      if (lossy) {
        // Reset all stored information that is parsed after this point,
        // just in case we've missed earlier lines in this header.
        _isolateStart = null;
        _vmStart = null;
      }
      return true;
    }
    match = _instructionsLineRE.firstMatch(line);
    if (match != null) {
      _isolateStart = int.parse(match[1]!, radix: 16);
      _vmStart = int.parse(match[2]!, radix: 16);
      if (_units != null) {
        final rootUnit = _units![constants.rootLoadingUnitId];
        if (lossy && rootUnit == null) {
          // We missed the header entry for the root loading unit, but it can
          // be reconstructed from other header lines.
          _units![constants.rootLoadingUnitId] = LoadingUnit(
            constants.rootLoadingUnitId,
            _isolateDsoBase!,
            _isolateStart!,
            buildId: _buildId,
          );
        } else {
          assert(rootUnit != null);
          assert(_isolateStart == rootUnit!.start);
          assert(_isolateDsoBase == rootUnit!.dsoBase);
          assert(_buildId == null || _buildId == rootUnit!.buildId);
        }
      }
      return true;
    }
    return false;
  }

  // Returns the closest positive offset, unless both offsets are negative in
  // which case it returns the negative offset closest to zero.
  int _closestOffset(int offset1, int offset2) {
    if (offset1 < 0) {
      if (offset2 < 0) return max(offset1, offset2);
      return offset2;
    }
    if (offset2 < 0) return offset1;
    return min(offset1, offset2);
  }

  /// The [PCOffset] for the given absolute program counter address.
  PCOffset? offsetOf(int address) {
    if (_isolateStart == null || _vmStart == null) return null;
    var vmOffset = address - _vmStart!;
    var unitOffset = address - _isolateStart!;
    var unitBuildId = _buildId;
    var unitId = constants.rootLoadingUnitId;
    if (units != null) {
      for (final unit in units!.values) {
        final newOffset = address - unit.start;
        if (newOffset == _closestOffset(unitOffset, newOffset)) {
          unitOffset = newOffset;
          unitBuildId = unit.buildId;
          unitId = unit.id;
        }
      }
    }
    if (unitOffset == _closestOffset(vmOffset, unitOffset)) {
      return PCOffset(unitOffset, InstructionsSection.isolate,
          os: _os,
          architecture: _arch,
          compressedPointers: _compressed,
          usingSimulator: _simulated,
          buildId: unitBuildId,
          unitId: unitId);
    }
    // The VM section is always stored in the root loading unit.
    return PCOffset(vmOffset, InstructionsSection.vm,
        os: _os,
        architecture: _arch,
        compressedPointers: _compressed,
        usingSimulator: _simulated,
        buildId: _buildId,
        unitId: constants.rootLoadingUnitId);
  }

  void writeToStringBuffer(StringBuffer buffer) {
    var printedField = false;
    void printField(String name, dynamic value) {
      buffer
        ..writeln(printedField ? ',' : '')
        ..write('  ')
        ..write(name)
        ..write(': ')
        ..write(value);
      printedField = true;
    }

    buffer.write('StackTraceHeader(');
    if (_vmStart != null) {
      printField('vmStart', _vmStart!.toRadixString(16));
    }
    if (_isolateStart != null) {
      printField('isolateStart', _isolateStart!.toRadixString(16));
    }
    if (_isolateDsoBase != null) {
      printField('isolateDsoBase', _isolateDsoBase!.toRadixString(16));
    }
    if (_arch != null) {
      final b = StringBuffer();
      if (_simulated == true) {
        b.write('SIM');
      }
      b.write(_arch!.toUpperCase());
      if (_compressed == true) {
        b.write('C');
      }
      printField('arch', b.toString());
    } else {
      if (_simulated != null) {
        printField('simulated', _simulated);
      }
      if (_compressed != null) {
        printField('compressed', _compressed);
      }
    }
    if (_buildId != null) {
      printField('buildId', "'$_buildId'");
    }
    if (_units != null) {
      final b = StringBuffer();
      b.writeln('{');
      for (final unitId in _units!.keys) {
        b.write('    $unitId => ');
        _units![unitId]!.writeToStringBuffer(b);
        b.writeln(',');
      }
      b.write('}');
      printField('units', b.toString());
    }
    buffer.write(')');
  }

  @override
  String toString() {
    final buffer = StringBuffer();
    writeToStringBuffer(buffer);
    return buffer.toString();
  }
}

(InstructionsSection, int)? _tryParseSymbolOffset(String s,
    {bool forceHexadecimal = false}) {
  final match = _symbolOffsetRE.firstMatch(s);
  if (match == null) return null;
  final symbolString = match.namedGroup('symbol')!;
  final offsetString = match.namedGroup('offset')!;
  int? offset;
  if (!forceHexadecimal && !offsetString.startsWith('0x')) {
    offset = int.tryParse(offsetString);
  }
  if (offset == null) {
    final digits = offsetString.startsWith('0x')
        ? offsetString.substring(2)
        : offsetString;
    offset = int.tryParse(digits, radix: 16);
  }
  if (offset == null) return null;
  switch (symbolString) {
    case constants.oldVmSymbolName:
      return (InstructionsSection.vm, offset);
    case constants.oldIsolateSymbolName:
      return (InstructionsSection.isolate, offset);
    case constants.dataSymbolName:
      return (InstructionsSection.isolate, offset);
    default:
      break;
  }
  return null;
}

/// Parses strings of the format `<static symbol>+<integer offset>`, where
/// `<static symbol>` is one of the static symbols used for Dart instruction
/// sections.
///
/// Unless forceHexadecimal is true, an integer offset without a "0x" prefix or
/// any hexadecimal digits will be parsed as decimal.
///
/// Assumes that the symbol should be resolved in the root loading unit.
///
/// Returns null if the string is not of the expected format.
PCOffset? tryParseSymbolOffset(String s,
    {bool forceHexadecimal = false,
    String? buildId,
    StackTraceHeader? header}) {
  final result = _tryParseSymbolOffset(s, forceHexadecimal: forceHexadecimal);
  if (result == null) return null;
  return PCOffset(result.$2, result.$1,
      os: header?.os,
      architecture: header?.architecture,
      compressedPointers: header?.compressedPointers,
      usingSimulator: header?.usingSimulator,
      buildId: header?.buildId,
      unitId: constants.rootLoadingUnitId);
}

/// A Dart DWARF stack trace contains up to four pieces of information:
///   - The zero-based frame index from the top of the stack.
///   - The absolute address of the program counter.
///   - The virtual address of the program counter, if the snapshot was
///     loaded as a dynamic library, otherwise not present.
///   - The location of the virtual address, which is one of the following:
///     - A dynamic symbol name, a plus sign, and an integer offset.
///     - The path to the snapshot, if it was loaded as a dynamic library,
///       otherwise the string `"<unknown>"`.
const _symbolOffsetREString = r'(?<symbol>' +
    constants.textSymbolName +
    r'|' +
    constants.oldVmSymbolName +
    r'|' +
    constants.oldIsolateSymbolName +
    r')\+(?<offset>(?:0x)?[\da-f]+)';
final _symbolOffsetRE = RegExp(_symbolOffsetREString);
final _traceLineRE = RegExp(r'\s*#(\d+) abs (?<absolute>[\da-f]+)'
    r'(?: unit (?<unitId>\d+))?'
    r'(?: virt (?<virtual>[\da-f]+))?'
    r' (?<rest>.*)$');

PCOffset? _retrievePCOffset(StackTraceHeader header, RegExpMatch? match) {
  if (match == null) return null;
  // Retrieve the unit ID for this stack frame, if one was provided.
  var unitId = constants.rootLoadingUnitId;
  var buildId = header.buildId;
  if (match.namedGroup('unitId') != null) {
    unitId = int.parse(match.namedGroup('unitId')!);
    final unit = header.units?[unitId];
    if (unit == null) {
      // The given non-root loading unit wasn't found in the header.
      return null;
    }
    buildId = unit.buildId;
  }
  if (unitId == constants.rootLoadingUnitId) {
    // Try checking for symbol information first, since we don't need the header
    // information to translate it for the root loading unit.
    final restString = match.namedGroup('rest')!;
    if (restString.isNotEmpty) {
      final result = _tryParseSymbolOffset(restString);
      if (result != null) {
        return PCOffset(result.$2, result.$1,
            os: header.os,
            architecture: header.architecture,
            compressedPointers: header.compressedPointers,
            usingSimulator: header.usingSimulator,
            buildId: buildId,
            unitId: unitId);
      }
    }
  }
  // If we're parsing the absolute address, we can only convert it into
  // a PCOffset if we saw the instructions line of the stack trace header.
  final addressString = match.namedGroup('absolute')!;
  final address = int.parse(addressString, radix: 16);
  final pcOffset = header.offsetOf(address);
  if (pcOffset != null) return pcOffset;
  // If all other cases failed, check for a virtual address. Until this package
  // depends on a version of Dart which only prints virtual addresses when the
  // virtual addresses in the snapshot are the same as in separately saved
  // debugging information, the other methods should be tried first.
  if (match.namedGroup('virtual') != null) {
    final address = int.parse(match.namedGroup('virtual')!, radix: 16);
    return PCOffset(address, InstructionsSection.none,
        os: header.os,
        architecture: header.architecture,
        compressedPointers: header.compressedPointers,
        usingSimulator: header.usingSimulator,
        buildId: buildId,
        unitId: unitId);
  }
  return null;
}

/// The [PCOffset]s for frames of the non-symbolic stack traces in [lines].
Iterable<PCOffset> collectPCOffsets(Iterable<String> lines,
    {bool lossy = false}) sync* {
  final header = StackTraceHeader();
  for (var line in lines) {
    if (header.tryParseHeaderLine(line, lossy: lossy)) {
      continue;
    }
    final match = _traceLineRE.firstMatch(line);
    final offset = _retrievePCOffset(header, match);
    if (offset != null) yield offset;
  }
}

/// A [StreamTransformer] that scans lines for non-symbolic stack traces.
///
/// A [NativeStackTraceDecoder] scans a stream of lines for non-symbolic
/// stack traces containing only program counter address information. Such
/// stack traces are generated by the VM when executing a snapshot compiled
/// with `--dwarf-stack-traces`.
///
/// The transformer assumes that there may be text preceding the stack frames
/// on individual lines, like in log files, but that there is no trailing text.
/// For each stack frame found, the transformer attempts to locate a function
/// name, file name and line number using the provided DWARF information.
///
/// If no information is found, or the line is not a stack frame, then the line
/// will be unchanged in the output stream.
///
/// If the located information corresponds to Dart internals and
/// [includeInternalFrames] is false, then the output stream contains no
/// entries for the line.
///
/// Otherwise, the output stream contains one or more lines with symbolic stack
/// frames for the given non-symbolic stack frame line. Multiple symbolic stack
/// frame lines are generated when the PC address corresponds to inlined code.
/// In the output stream, each symbolic stack frame is prefixed by the non-stack
/// frame portion of the original line.
class DwarfStackTraceDecoder extends StreamTransformerBase<String, String> {
  final Dwarf _dwarf;
  final Map<int, Dwarf>? _dwarfByUnitId;
  final Iterable<Dwarf>? _unitDwarfs;
  final bool _includeInternalFrames;

  DwarfStackTraceDecoder(
    this._dwarf, {
    Map<int, Dwarf>? dwarfByUnitId,
    Iterable<Dwarf>? unitDwarfs,
    bool includeInternalFrames = false,
  })  : _dwarfByUnitId = dwarfByUnitId,
        _unitDwarfs = unitDwarfs,
        _includeInternalFrames = includeInternalFrames;

  @override
  Stream<String> bind(Stream<String> stream) async* {
    var depth = 0;
    final header = StackTraceHeader();
    await for (final line in stream) {
      // If we successfully parse a header line, then we reset the depth to 0.
      if (header.tryParseHeaderLine(line, lossy: true)) {
        depth = 0;
        yield line;
        continue;
      }
      // 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);
      if (offset == null) {
        yield line;
        continue;
      }
      Dwarf dwarf = _dwarf;
      final unitId = offset.unitId;
      if (unitId != null && unitId != constants.rootLoadingUnitId) {
        Dwarf? unitDwarf;
        // Prefer the map that specifies loading unit IDs over the iterable.
        if (_dwarfByUnitId != null) {
          unitDwarf = _dwarfByUnitId[unitId];
        }
        if (unitDwarf == null &&
            _unitDwarfs != null &&
            offset.buildId != null) {
          for (final d in _unitDwarfs) {
            if (d.buildId(offset.architecture) == offset.buildId) {
              unitDwarf = d;
            }
          }
        }
        // Don't attempt to translate if we couldn't find the correct debugging
        // information for this loading unit.
        if (unitDwarf == null) {
          yield line;
          continue;
        }
        dwarf = unitDwarf;
      }
      final callInfo = offset.callInfoFrom(dwarf,
          includeInternalFrames: _includeInternalFrames);
      if (callInfo == null) {
        yield line;
        continue;
      }
      // No lines to output (as this corresponds to Dart internals).
      if (callInfo.isEmpty) continue;
      // Output the lines for the symbolic frame with the prefix found on the
      // original non-symbolic frame line, modulo all whitespace between the
      // prefix and stack trace information converted to a single space.
      //
      // If there was no prefix, just swallow any initial whitespace, since
      // symbolic Dart stacktrace lines have no initial whitespace.
      String prefix = line.substring(0, lineMatch!.start);
      if (prefix.isNotEmpty) {
        prefix += ' ';
      }
      for (final call in callInfo) {
        yield prefix + _stackTracePiece(call, depth++);
      }
    }
  }
}
