// 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_SEGMENT = 0x1;
  static const LC_SYMTAB = 0x2;
  static const LC_SEGMENT_64 = 0x19;
  static const LC_UUID = 0x1b;
  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;
      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 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.sections)
      : 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 sections = <String, Section>{};
    for (int i = 0; i < nsects; i++) {
      final section = Section.fromReader(reader);
      sections[section.sectname] = section;
    }
    return SegmentCommand._(cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
        filesize, maxprot, initprot, nsects, flags, sections);
  }

  @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 sections.values) {
      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 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 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<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.vmSymbolName]?.value;

  @override
  int? get isolateStartAddress =>
      _symbolTable[constants.isolateSymbolName]?.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;
}
