public MachOCoreDump()

in src/Microsoft.Diagnostics.Runtime/src/MacOS/MachOCoreDump.cs [39:158]


        public MachOCoreDump(Stream stream, bool leaveOpen, string displayName)
        {
            fixed (MachHeader64* header = &_header)
                if (stream.Read(new Span<byte>(header, sizeof(MachHeader64))) != sizeof(MachHeader64))
                    throw new IOException($"Failed to read header from {displayName}.");

            if (_header.Magic != MachHeader64.Magic64)
                throw new InvalidDataException($"'{displayName}' does not have a valid Mach-O header.");

            _stream = stream;
            _leaveOpen = leaveOpen;

            Dictionary<ulong, uint> threadIds = new Dictionary<ulong, uint>();
            List<thread_state_t> contexts = new List<thread_state_t>();
            List<MachOSegment> segments = new List<MachOSegment>((int)_header.NumberCommands);

            for (int i = 0; i < _header.NumberCommands; i++)
            {
                long position = stream.Position;
                LoadCommandHeader loadCommand = new LoadCommandHeader();
                stream.Read(new Span<byte>(&loadCommand, sizeof(LoadCommandHeader)));
                
                long next = position + loadCommand.Size;

                switch (loadCommand.Kind)
                {
                    case LoadCommandType.Segment64:
                        Segment64LoadCommand seg = default;
                        stream.Read(new Span<byte>(&seg, sizeof(Segment64LoadCommand)));

                        if (seg.VMAddr == SpecialThreadInfoHeader.SpecialThreadInfoAddress)
                        {
                            stream.Position = (long)seg.FileOffset;

                            SpecialThreadInfoHeader threadInfo = Read<SpecialThreadInfoHeader>(stream);
                            if (threadInfo.Signature != SpecialThreadInfoHeader.SpecialThreadInfoSignature)
                            {
                                segments.Add(new MachOSegment(seg));
                            }
                            else
                            {
                                for (int j = 0; j < threadInfo.NumberThreadEntries; j++)
                                {
                                    SpecialThreadInfoEntry threadEntry = Read<SpecialThreadInfoEntry>(stream);
                                    threadIds[threadEntry.StackPointer] = threadEntry.ThreadId;
                                }
                            }
                        }
                        else
                        {
                            segments.Add(new MachOSegment(seg));
                        }
                        break;
                    
                    case LoadCommandType.Thread:
                        thread_state_t threadState = default;
                        uint flavor = Read<uint>(stream);
                        uint count = Read<uint>(stream);

                        switch (_header.CpuType)
                        {
                            case MachOCpuType.X86_64:
                                if (flavor == X86_THREAD_STATE64)
                                {
                                    threadState.x64 = Read<x86_thread_state64_t>(stream);
                                }
                                break;

                            case MachOCpuType.ARM64:
                                if (flavor == ARM_THREAD_STATE64)
                                {
                                    threadState.arm = Read<arm_thread_state64_t>(stream);
                                }
                                break;
                        }
                        contexts.Add(threadState);
                        break;
                }

                stream.Seek(next, SeekOrigin.Begin);
            }

            segments.Sort((x, y) => x.Address.CompareTo(y.Address));
            _segments = segments.ToArray();

            foreach (MachOSegment seg in _segments)
            {
                MachHeader64 header = ReadMemory<MachHeader64>(seg.Address);
                if (header.Magic == MachHeader64.Magic64 && header.FileType == MachOFileType.Dylinker)
                {
                    _dylinker = new MachOModule(this, seg.Address, "dylinker");
                    break;
                }
            }

            Dictionary<uint, thread_state_t> threadContexts = new();
            for (int i = 0; i < contexts.Count; i++)
            {
                ulong esp = default;
                switch (_header.CpuType)
                {
                    case MachOCpuType.X86_64:
                        esp = contexts[i].x64.__rsp;
                        break;
                    case MachOCpuType.ARM64:
                        esp = contexts[i].arm.__sp;
                        break;
                }
                if (threadIds.TryGetValue(esp, out uint threadId))
                {
                    threadContexts.Add(threadId, contexts[i]);
                }
                else
                {
                    // Use the index as the thread id if the special thread info memory section doesn't exists
                    threadContexts.Add((uint)i, contexts[i]);
                }
            }
            Threads = threadContexts.ToImmutableDictionary();
        }