// 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:io';
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_REQ_DYLD = 0x80000000;

  static const LC_SEGMENT = 0x1;
  static const LC_SYMTAB = 0x2;
  static const LC_ID_DYLIB = 0xd;
  static const LC_SEGMENT_64 = 0x19;
  static const LC_UUID = 0x1b;
  static const LC_RPATH = 0x1c | LC_REQ_DYLD;
  static const LC_CODE_SIGNATURE = 0x1d; // Only used in vm/dart tests.
  static const LC_ENCRYPTION_INFO = 0x21;
  static const LC_ENCRYPTION_INFO_64 = 0x2c;
  static const LC_BUILD_VERSION = 0x32;

  static LoadCommand fromReader(Reader reader) {
    final start = reader.offset; // cmdsize includes size of cmd and cmdsize.
    final cmd = _readMachOUint32(reader);
    final cmdsize = _readMachOUint32(reader);
    assert(reader.remaining >= cmdsize - (reader.offset - start));
    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;
      case LC_UUID:
        command = UuidCommand.fromReader(reader, cmd, cmdsize);
        break;
      case LC_BUILD_VERSION:
        command = BuildVersionCommand.fromReader(reader, cmd, cmdsize);
        break;
      case LC_ID_DYLIB:
        command = DylibCommand.fromReader(reader, cmd, cmdsize);
      case LC_RPATH:
        command = RunPathCommand.fromReader(reader, cmd, cmdsize);
      case LC_ENCRYPTION_INFO:
      case LC_ENCRYPTION_INFO_64:
        command = EncryptionInfoCommand.fromReader(reader, cmd, cmdsize);
      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 List<Section> sectionsInOrder;
  final Map<String, Section> sections;

  SegmentCommand._(
      super.cmd,
      super.cmdsize,
      this.segname,
      this.vmaddr,
      this.vmsize,
      this.fileoff,
      this.filesize,
      this.maxprot,
      this.initprot,
      this.nsects,
      this.flags,
      this.sectionsInOrder)
      : sections = Map.fromEntries(
            sectionsInOrder.map((s) => MapEntry(s.sectname, s))),
        super._();

  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 sectionsInOrder = <Section>[];
    for (int i = 0; i < nsects; i++) {
      final section = Section.fromReader(reader);
      sectionsInOrder.add(section);
    }
    return SegmentCommand._(cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
        filesize, maxprot, initprot, nsects, flags, sectionsInOrder);
  }

  @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 sectionsInOrder) {
      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 shrink(Reader reader) => reader.shrink(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._(super.cmd, super.cmdsize, this._symoff, this._nsyms,
      this._stroff, this._strsize)
      : super._();

  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.shrink(_stroff, _strsize));
    return SymbolTable.fromReader(reader.shrink(_symoff), _nsyms, stringTable);
  }

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('Symbol table with ')
      ..write(_nsyms)
      ..write(' symbols of size ')
      ..writeln(cmdsize);
  }
}

class UuidCommand extends LoadCommand {
  Uint8List uuid;

  static const kUuidSize = 16;

  UuidCommand._(super.cmd, super.cmdsize, this.uuid) : super._();

  static UuidCommand fromReader(Reader reader, int cmd, int cmdsize) {
    final uuid = Uint8List.sublistView(
        reader.bytes, reader.offset, reader.offset + kUuidSize);
    return UuidCommand._(cmd, cmdsize, uuid);
  }

  String get uuidString => uuid.map((i) => paddedHex(i, 1)).join();

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('UUID: ')
      ..write(uuidString);
  }
}

class DylibInfo {
  final String name;
  final int timestamp;
  final int currentVersion;
  final int compatibilityVersion;

  const DylibInfo._(this.name, this.timestamp, this.currentVersion,
      this.compatibilityVersion);

  static DylibInfo fromReader(Reader reader, int cmdsize) {
    final start = reader.offset - 8; // cmd + cmdsize
    final offset = _readMachOUint32(reader);
    final timestamp = _readMachOUint32(reader);
    final currentVersion = _readMachOUint32(reader);
    final compatibilityVersion = _readMachOUint32(reader);
    reader.seek(start + offset, absolute: true);
    final name = reader.readNullTerminatedString(maxSize: cmdsize - offset);
    return DylibInfo._(name, timestamp, currentVersion, compatibilityVersion);
  }

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('  Name: ')
      ..writeln(name)
      ..write('  Timestamp: ')
      ..writeln(timestamp)
      ..write('  Current version: ')
      ..writeln(currentVersion)
      ..write('  Compatibility version: ')
      ..writeln(compatibilityVersion);
  }

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

class DylibCommand extends LoadCommand {
  final DylibInfo info;

  DylibCommand._(super.cmd, super.cmdsize, this.info) : super._();

  static DylibCommand fromReader(Reader reader, int cmd, int cmdsize) =>
      DylibCommand._(cmd, cmdsize, DylibInfo.fromReader(reader, cmdsize));

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    if (cmd == LoadCommand.LC_ID_DYLIB) {
      buffer.writeln('LC_ID_DYLIB:');
      info.writeToStringBuffer(buffer);
    } else {
      throw StateError("Unexpected command code $cmd");
    }
  }
}

class RunPathCommand extends LoadCommand {
  String path;

  RunPathCommand._(super.cmd, super.cmdsize, this.path) : super._();

  static RunPathCommand fromReader(Reader reader, int cmd, int cmdsize) {
    final start = reader.offset - 8; // cmd + cmdsize
    final offset = _readMachOUint32(reader);
    reader.seek(start + offset, absolute: true);
    final path = reader.readNullTerminatedString(maxSize: cmdsize - offset);
    return RunPathCommand._(cmd, cmdsize, path);
  }

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('Run path: ')
      ..write(path);
  }
}

class Version {
  final int x;
  final int y;
  final int z;

  const Version(this.x, this.y, this.z);

  static Version fromInt(int v) {
    final x = (v & 0xffffffff) >> 16;
    final y = (v & 0xffff) >> 8;
    final z = v & 0xff;
    return Version(x, y, z);
  }

  @override
  int get hashCode => Object.hash(x, y, z);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is Version && x == other.x && y == other.y && z == other.z;
  }

  @override
  String toString() => '$x.$y.$z';
}

enum Platform {
  PLATFORM_UNKNOWN(0, 'Unknown'),
  PLATFORM_ANY(0xFFFFFFFF, 'any'),
  PLATFORM_MACOS(0x1, 'MacOS'),
  PLATFORM_IOS(0x2, 'iOS'),
  PLATFORM_TVOS(0x3, 'TVOS'),
  PLATFORM_WATCHOS(0x4, 'WatchOS'),
  PLATFORM_IOSSIMULATOR(0x7, 'iOS Simulator'),
  PLATFORM_TVOSSIMULATOR(0x8, 'TVOS Simulator'),
  PLATFORM_WATCHOSSIMULATOR(0x9, 'WatchOS Simulator');

  final int id;
  final String description;

  const Platform(this.id, this.description);

  static Platform? fromId(int id) {
    for (final platform in values) {
      if (platform.id == id) {
        return platform;
      }
    }
    return null;
  }

  @override
  String toString() => description;
}

enum BuildTool {
  TOOL_CLANG(1, 'clang'),
  TOOL_SWIFT(2, 'Swift'),
  TOOL_LD(3, 'ld'),
  TOOL_LLD(4, 'lld');

  final int id;
  final String description;

  const BuildTool(this.id, this.description);

  static BuildTool? fromId(int id) {
    for (final tool in values) {
      if (tool.id == id) {
        return tool;
      }
    }
    return null;
  }

  @override
  String toString() => description;
}

class BuildToolVersion {
  final int _toolId;
  final BuildTool? tool;
  final Version version;

  const BuildToolVersion._(this._toolId, this.tool, this.version);

  factory BuildToolVersion.fromReader(Reader reader) {
    final id = _readMachOUint32(reader);
    final tool = BuildTool.fromId(id);
    final version = Version.fromInt(_readMachOUint32(reader));
    return BuildToolVersion._(id, tool, version);
  }

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('  - ')
      ..write(tool ?? 'Unknown (0x${paddedHex(_toolId, 4)})')
      ..write(' (')
      ..write(version)
      ..writeln(')');
  }

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

class BuildVersionCommand extends LoadCommand {
  final int _platformId;
  final Platform? platform;
  final Version minOS;
  final Version sdk;
  final List<BuildToolVersion> toolVersions;

  BuildVersionCommand._(super.cmd, super.cmdsize, this._platformId,
      this.platform, this.minOS, this.sdk, this.toolVersions)
      : super._();

  static BuildVersionCommand fromReader(Reader reader, int cmd, int cmdsize) {
    final platformId = _readMachOUint32(reader);
    final platform = Platform.fromId(platformId);
    final minOS = Version.fromInt(_readMachOUint32(reader));
    final sdk = Version.fromInt(_readMachOUint32(reader));
    final toolCount = _readMachOUint32(reader);
    final toolVersions = <BuildToolVersion>[];
    for (int i = 0; i < toolCount; i++) {
      toolVersions.add(BuildToolVersion.fromReader(reader));
    }
    return BuildVersionCommand._(
        cmd, cmdsize, platformId, platform, minOS, sdk, toolVersions);
  }

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..writeln('Build version:')
      ..write('  Platform: ')
      ..writeln(platform ?? 'Unknown (0x${paddedHex(_platformId, 4)})')
      ..write('  Minimum OS: ')
      ..writeln(minOS)
      ..write('  Minimum SDK: ')
      ..writeln(sdk);
    if (toolVersions.isNotEmpty) {
      buffer.writeln('  Tools:');
      for (final v in toolVersions) {
        v.writeToStringBuffer(buffer);
      }
    }
  }
}

class EncryptionInfoCommand extends LoadCommand {
  final int fileOffset;
  final int fileSize;
  final int cryptId;

  EncryptionInfoCommand._(
      super.cmd, super.cmdsize, this.fileOffset, this.fileSize, this.cryptId)
      : super._();

  static EncryptionInfoCommand fromReader(Reader reader, int cmd, int cmdsize) {
    final fileOffset = _readMachOUint32(reader);
    final fileSize = _readMachOUint32(reader);
    final cryptId = _readMachOUint32(reader);
    if (cmd == LoadCommand.LC_ENCRYPTION_INFO_64) {
      _readMachOUint32(reader); // padding
    }
    return EncryptionInfoCommand._(cmd, cmdsize, fileOffset, fileSize, cryptId);
  }

  @override
  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..writeln('Encryption info: ')
      ..write('  File offset: ')
      ..writeln(paddedHex(fileOffset, 4))
      ..write('  File size: ')
      ..writeln(fileSize)
      ..write('  Crypt id: ')
      ..writeln(cryptId);
  }
}

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 const _MH_DSYM = 0xa;

  static int? _wordSize(int magic) => (magic == _MH_MAGIC || magic == _MH_CIGAM)
      ? 4
      : (magic == _MH_MAGIC_64 || magic == _MH_CIGAM_64)
          ? 8
          : null;

  static Endian? _endian(int magic) =>
      (magic == _MH_MAGIC || magic == _MH_MAGIC_64)
          ? Endian.host
          : (magic == _MH_CIGAM || magic == _MH_CIGAM_64)
              ? (Endian.host == Endian.big ? Endian.little : Endian.big)
              : null;

  static MachOHeader? fromReader(Reader reader) {
    final start = reader.offset;
    // Initially assume host endianness.
    reader.endian = Endian.host;
    final magic = _readMachOUint32(reader);
    final wordSize = _wordSize(magic);
    final endian = _endian(magic);
    // Not an expected magic value, so not a supported Mach-O file.
    if (wordSize == null || endian == null) return null;
    reader.wordSize = wordSize;
    reader.endian = endian;
    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);
  }

  int get wordSize => _wordSize(magic)!;
  Endian get endian => _endian(magic)!;
  bool get isDSYM => filetype == _MH_DSYM;

  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 extends DwarfContainer {
  final MachOHeader header;
  final List<LoadCommand> _commands;
  final SymbolTable _symbolTable;
  final SegmentCommand? _dwarfSegment;
  final StringTable? _debugStringTable;
  final StringTable? _debugLineStringTable;

  MachO._(this.header, this._commands, this._symbolTable, this._dwarfSegment,
      this._debugStringTable, this._debugLineStringTable);

  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 = machOReader.shrink(machOReader.offset);
    final header = MachOHeader.fromReader(reader);
    if (header == null) return null;

    final commandReader = reader.shrink(reader.offset, header.sizeofcmds);
    final commands =
        List.of(commandReader.readRepeated(LoadCommand.fromReader));
    assert(commands.length == header.ncmds);

    // This MachO file can't contain any debugging information.
    if (commands.isEmpty) return null;

    final symbolTable =
        commands.whereType<SymbolTableCommand>().single.load(reader);

    final dwarfSegment = commands
        .whereType<SegmentCommand?>()
        .firstWhere((sc) => sc!.segname == '__DWARF', orElse: () => null);
    StringTable? debugStringTable;
    StringTable? debugLineStringTable;
    if (dwarfSegment != null) {
      final debugStringTableSection = dwarfSegment.sections['__debug_str'];
      if (debugStringTableSection != null) {
        debugStringTable =
            StringTable.fromReader(debugStringTableSection.shrink(reader));
      }

      final debugLineStringTableSection =
          dwarfSegment.sections['__debug_line_str'];
      if (debugLineStringTableSection != null) {
        debugLineStringTable =
            StringTable.fromReader(debugLineStringTableSection.shrink(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,
        debugStringTable, debugLineStringTable);
  }

  static String handleDSYM(String fileName) {
    if (!fileName.endsWith('.dSYM')) {
      return fileName;
    }
    final dwarfDir =
        Directory(path.join(fileName, 'Contents', 'Resources', 'DWARF'));
    // The DWARF directory inside the .dSYM should contain a single MachO file.
    final machoFile = dwarfDir.listSync().single as File;
    return machoFile.path;
  }

  static MachO? fromFile(String fileName) =>
      MachO.fromReader(Reader.fromFile(MachO.handleDSYM(fileName)));

  bool get isDSYM => header.isDSYM;
  bool get hasDwarf => _dwarfSegment != null;

  Reader applyWordSizeAndEndian(Reader reader) =>
      Reader.fromTypedData(reader.bdata,
          wordSize: header.wordSize, endian: header.endian);

  Iterable<LoadCommand> get commands => _commands;
  Iterable<T> commandsWhereType<T extends LoadCommand>() =>
      _commands.whereType<T>();

  @override
  String? get architecture => CpuType.fromCode(header.cputype)?.dartName;

  @override
  Reader? abbreviationsTableReader(Reader containerReader) =>
      _dwarfSegment?.sections['__debug_abbrev']?.shrink(containerReader);
  @override
  Reader? lineNumberInfoReader(Reader containerReader) =>
      _dwarfSegment?.sections['__debug_line']?.shrink(containerReader);
  @override
  Reader? debugInfoReader(Reader containerReader) =>
      _dwarfSegment?.sections['__debug_info']?.shrink(containerReader);

  @override
  int? get vmStartAddress => _symbolTable[constants.oldVmSymbolName]?.value;

  @override
  int? get isolateStartAddress =>
      _symbolTable[constants.textSymbolName]?.value ??
      _symbolTable[constants.oldIsolateSymbolName]?.value;

  @override
  String? get buildId =>
      _commands.whereType<UuidCommand>().firstOrNull?.uuidString;

  @override
  DwarfContainerStringTable? get debugStringTable => _debugStringTable;

  @override
  DwarfContainerStringTable? get debugLineStringTable => _debugLineStringTable;

  @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
  Iterable<Symbol> get staticSymbols => _symbolTable.values;

  @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('');
    }
  }
}

class UniversalBinaryArch {
  final int cputype;
  final int cpusubtype;
  final int offset;
  final int size;
  final int align;

  UniversalBinaryArch._(
      this.cputype, this.cpusubtype, this.offset, this.size, this.align);

  static UniversalBinaryArch fromReader(Reader reader) {
    final cputype = _readMachOUint32(reader);
    final cpusubtype = _readMachOUint32(reader);
    final offset = _readMachOUint32(reader);
    final size = _readMachOUint32(reader);
    final align = _readMachOUint32(reader);

    return UniversalBinaryArch._(cputype, cpusubtype, offset, size, align);
  }

  // Given a reader for the entire universal binary, returns a reader
  // for only this architecture's contents.
  Reader shrink(Reader reader) => reader.shrink(offset, size);

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('  Cpu Type: 0x')
      ..writeln(paddedHex(cputype, 4));
    buffer
      ..write('  Cpu Subtype: 0x')
      ..writeln(paddedHex(cpusubtype, 4));
    buffer
      ..write('  Offset: 0x')
      ..writeln(paddedHex(offset, 4));
    buffer
      ..write('  Size: ')
      ..writeln(size);
    buffer
      ..write('  Alignment: ')
      ..writeln(align);
  }

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

class UniversalBinaryHeader {
  final int magic;
  final List<UniversalBinaryArch> _arches;

  UniversalBinaryHeader._(this.magic, this._arches);

  static const _FAT_MAGIC = 0xcafebabe;
  static const _FAT_CIGAM = 0xbebafeca;

  static UniversalBinaryHeader? fromReader(Reader originalReader) {
    assert(originalReader.offset == 0);
    // Make sure we have a reader that makes no assumptions about the
    // endianness, since we'll read that in the header.
    final reader =
        Reader.fromTypedData(ByteData.sublistView(originalReader.bdata));
    reader.wordSize = 4;
    reader.endian = Endian.host;
    final magic = _readMachOUint32(reader);
    if (magic == _FAT_CIGAM) {
      reader.endian = Endian.host == Endian.big ? Endian.little : Endian.big;
    } else if (magic != _FAT_MAGIC) {
      // Not a universal binary.
      return null;
    }
    final archCount = _readMachOUint32(reader);
    final arches = <UniversalBinaryArch>[];
    for (int i = 0; i < archCount; i++) {
      arches.add(UniversalBinaryArch.fromReader(reader));
    }
    return UniversalBinaryHeader._(magic, arches);
  }

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..write('Magic: 0x')
      ..writeln(paddedHex(magic, 4));
    buffer
      ..write('Number of architectures: ')
      ..writeln(_arches.length);
    for (int i = 0; i < _arches.length; i++) {
      buffer
        ..write('Arch ')
        ..write(i)
        ..writeln(':');
      _arches[i].writeToStringBuffer(buffer);
    }
  }

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

/// Represents Dart architectures that have valid CPU type values in MachO.
enum CpuType {
  arm(_CPU_ARCH_ARM, "arm"),
  arm64(_CPU_ARCH_ARM | _CPU_ARCH_ABI64, "arm64"),
  i386(_CPU_ARCH_X86, "ia32"),
  x64(_CPU_ARCH_X86 | _CPU_ARCH_ABI64, "x64");

  static const _CPU_ARCH_ABI64 = 0x01000000;
  static const _CPU_ARCH_X86 = 7;
  static const _CPU_ARCH_ARM = 12;

  static const _prefix = 'CPU_ARCH';

  /// The 32-bit MachO encoding for this architecture.
  final int code;

  /// The name of this architecture as reported by Dart, e.g., in
  /// non-symbolic stack traces.
  final String dartName;

  const CpuType(this.code, this.dartName);

  static CpuType? fromCode(int code) {
    for (final value in values) {
      if (value.code == code) return value;
    }
    return null;
  }

  static CpuType? fromDartName(String arch) {
    for (final value in values) {
      if (value.dartName == arch) return value;
    }
    return null;
  }

  /// Whether this CpuType represents a 64-bit architecture.
  bool get is64Bit => code & _CPU_ARCH_ABI64 != 0;

  @override
  String toString() => '${_prefix}_${name.toUpperCase()}';
}

class UniversalBinary {
  final UniversalBinaryHeader _header;
  final Map<CpuType, UniversalBinaryArch> _arches;
  final Map<UniversalBinaryArch, MachO> _contents;

  UniversalBinary._(this._header, this._arches, this._contents);

  static UniversalBinary? fromReader(Reader originalReader) {
    // Universal binary files contain absolute offsets from the start of the
    // file, so make sure we have a reader that has an internal offset of 0 so
    // absolute offsets can be used directly.
    final reader = originalReader.shrink(originalReader.offset);
    final header = UniversalBinaryHeader.fromReader(reader);
    if (header == null) {
      return null;
    }
    final arches = <CpuType, UniversalBinaryArch>{};
    final contents = <UniversalBinaryArch, MachO>{};
    for (final arch in header._arches) {
      final cpuType = CpuType.fromCode(arch.cputype);
      if (cpuType == null) continue;
      final archReader = arch.shrink(reader);
      final macho = MachO.fromReader(archReader);
      // The MachO parser either failed (likely due to a lack of debugging
      // information) or this contains debugging information for something other
      // than a Dart snapshot (since it contains neither a VM or isolate
      // instruction section symbol).
      if ((macho == null) ||
          ((macho.vmStartAddress == null) &&
              (macho.isolateStartAddress == null))) {
        continue;
      }
      if (!arches.containsKey(cpuType)) {
        arches[cpuType] = arch;
      } else if (macho.isDSYM) {
        // Always take a dSYM section above a non-dSYM section. If there are
        // multiple dSYM sections for some reason, the last one read is fine.
        arches[cpuType] = arch;
      } else if (!contents[arches[cpuType]!]!.hasDwarf) {
        // If the old section didn't have DWARF information but the new one
        // does, take it instead.
        arches[cpuType] = arch;
      }
      contents[arch] = macho;
    }
    return UniversalBinary._(header, arches, contents);
  }

  static UniversalBinary? fromFile(String fileName) =>
      UniversalBinary.fromReader(Reader.fromFile(MachO.handleDSYM(fileName)));

  Iterable<CpuType> get architectures => _arches.keys;

  Reader? readerForCpuType(Reader originalReader, CpuType cpuType) {
    final arch = _arches[cpuType];
    if (arch == null) return null;
    final macho = _contents[arch]!;
    // Universal binary files contain absolute offsets from the start of the
    // file, so make sure to feed arch.shrink a reader that has an internal
    // offset of 0.
    return macho.applyWordSizeAndEndian(
        arch.shrink(originalReader.shrink(originalReader.offset)));
  }

  DwarfContainer? containerForCpuType(CpuType cpuType) {
    final arch = _arches[cpuType];
    if (arch == null) return null;
    return _contents[arch];
  }

  void writeToStringBuffer(StringBuffer buffer) {
    buffer
      ..writeln('----------------------------------------')
      ..writeln('       Universal Binary Header')
      ..writeln('----------------------------------------')
      ..writeln('');
    _header.writeToStringBuffer(buffer);
    for (final cpuType in _arches.keys) {
      buffer
        ..writeln('')
        ..writeln('')
        ..writeln('----------------------------------------------------------')
        ..writeln('          Selected Mach-O Contents for $cpuType')
        ..writeln('----------------------------------------------------------')
        ..writeln('');
      _contents[_arches[cpuType]!]!.writeToStringBuffer(buffer);
    }
  }

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

const _magicByteOffset = 0;
const _cpuTypeByteOffset = 4;
const _fileTypeByteOffset = 12;

/// Used by certain Dart tests to create a MachO file that only contains a
/// header for the given architecture.
Uint8List? emptyMachOForArchitecture(String dartName) {
  final cpuType = CpuType.fromDartName(dartName);
  if (cpuType == null) return null;
  // 4 bytes * 7 fields + 4 padding bytes on 64-bit architectures.
  final contents = Uint8List(32);
  // We'll leave most of the fields at 0.
  final byteData = ByteData.sublistView(contents);
  // Use the host endian magic number marker corresponding to the bit size.
  byteData.setUint32(
      _magicByteOffset,
      cpuType.is64Bit ? MachOHeader._MH_MAGIC_64 : MachOHeader._MH_MAGIC,
      Endian.host);
  byteData.setUint32(_cpuTypeByteOffset, cpuType.code, Endian.host);
  // Just to set it to a valid file type, even though there are no contents.
  byteData.setUint32(_fileTypeByteOffset, MachOHeader._MH_DSYM, Endian.host);
  return contents;
}
