DumpReadResult GetModules(BinaryReader dumpReader)
        {
            ulong dumpSize   = (ulong)dumpReader.BaseStream.Length;
            var   moduleList = new List <DumpModule>();

            if (!ElfHeader.TryRead(dumpReader, out ElfHeader elfHeader))
            {
                return(new DumpReadResult(moduleList, DumpReadWarning.ElfHeaderIsCorrupted));
            }

            var             fileSections = new List <FileSection>();
            var             loadSegments = new List <ProgramHeader>();
            DumpReadWarning warning      = DumpReadWarning.None;

            // Go through each program header sections, look for the notes sections and the
            // loadable segments.
            for (ulong i = 0; i < elfHeader.EntriesCount; ++i)
            {
                ulong headerOffset = elfHeader.StartOffset + i * elfHeader.EntrySize;
                dumpReader.BaseStream.Seek((long)headerOffset, SeekOrigin.Begin);

                if (!ProgramHeader.TryRead(dumpReader, out ProgramHeader header))
                {
                    return(new DumpReadResult(moduleList, DumpReadWarning.FileIsTruncated));
                }

                // Set the warning if the program header is outside of the file.
                if (header.OffsetInFile + header.SizeInFile > dumpSize &&
                    warning == DumpReadWarning.None)
                {
                    warning = DumpReadWarning.FileIsTruncated;
                }

                switch (header.HeaderType)
                {
                // We found the notes section. Now we need to extract module section from
                // the NT_FILE notes.
                case ProgramHeader.Type.NoteSegment:
                    if (header.SizeInFile > int.MaxValue)
                    {
                        Trace.WriteLine("Can't extract note segment sections from program" +
                                        "header. Note size is more then int.Max.");
                        continue;
                    }

                    int size = (int)header.SizeInFile;
                    dumpReader.BaseStream.Seek((long)header.OffsetInFile, SeekOrigin.Begin);
                    byte[] notesBytes  = dumpReader.ReadBytes(size);
                    var    notesStream = new MemoryStream(notesBytes);
                    using (var notesReader = new BinaryReader(notesStream))
                    {
                        IEnumerable <FileSection> moduleSections =
                            NoteSection.ReadModuleSections(notesReader, size);
                        fileSections.AddRange(moduleSections);
                    }

                    break;

                // Collect memory mappings for the core files.
                case ProgramHeader.Type.LoadableSegment:
                    loadSegments.Add(header);
                    break;
                }
            }

            var loadableSegmentsReader = new ModuleReader(loadSegments, dumpReader);

            // Go through each module and try to find build id in the mapped regions.
            foreach (FileSection file in fileSections)
            {
                DumpModule module = loadableSegmentsReader.GetModule(file);
                if (module.Id == BuildId.Empty)
                {
                    Trace.WriteLine($"Can't find build id for module {module.Path}.");
                }
                else
                {
                    moduleList.Add(module);
                }
            }

            return(new DumpReadResult(moduleList, warning));
        }
示例#2
0
        /// <summary>
        /// Looks for build id for specified module index in core dump.
        /// Method also returns information about the module: is it executable and path.
        /// </summary>
        /// <returns>Dump module or DumpModule.Empty.</returns>
        public DumpModule GetModule(FileSection file)
        {
            byte[] elfHeaderBytes = ReadBlockByAddress(file.StartAddress, ElfHeader.Size);
            using (var elfHeaderReader = new BinaryReader(new MemoryStream(elfHeaderBytes)))
            {
                if (!ElfHeader.TryRead(elfHeaderReader, out ElfHeader moduleHeader))
                {
                    Trace.WriteLine($"Failed to read elf header for module {file.Path}.");
                    return(DumpModule.Empty);
                }

                int    headersSize = moduleHeader.EntriesCount * moduleHeader.EntrySize;
                byte[] headerBytes =
                    ReadBlockByAddress(file.StartAddress + moduleHeader.StartOffset, headersSize);

                using (var headerReader = new BinaryReader(new MemoryStream(headerBytes)))
                {
                    // Iterate through the program headers, until we find the note with the build
                    // id.
                    for (ulong i = 0; i < moduleHeader.EntriesCount; ++i)
                    {
                        ulong offset = i * moduleHeader.EntrySize;
                        headerReader.BaseStream.Seek((long)offset, SeekOrigin.Begin);
                        if (!ProgramHeader.TryRead(headerReader, out ProgramHeader header))
                        {
                            Trace.WriteLine(
                                $"Failed to read program header with offset: {offset} " +
                                $"from module {file.Path}.");
                            continue;
                        }

                        if (header.HeaderType != ProgramHeader.Type.NoteSegment)
                        {
                            continue;
                        }

                        ulong fileSize  = file.EndAddress - file.StartAddress;
                        ulong headerEnd = header.OffsetInFile + header.SizeInFile;
                        if (headerEnd > fileSize)
                        {
                            Trace.WriteLine(
                                "Can't extract note sections from program header. " +
                                "Note section is outside of the first mapped location.");
                            continue;
                        }

                        if (header.SizeInFile > int.MaxValue)
                        {
                            Trace.WriteLine("Can't extract note sections from program header. " +
                                            "Note size is more then int.Max.");
                            continue;
                        }

                        int    size             = (int)header.SizeInFile;
                        byte[] noteSegmentBytes =
                            ReadBlockByAddress(file.StartAddress + header.OffsetInFile, size);
                        if (noteSegmentBytes.Length < size)
                        {
                            Trace.WriteLine("Can't extract build ids from note section. " +
                                            "Note is not fully in load segments.");
                            continue;
                        }

                        var notesStream = new MemoryStream(noteSegmentBytes);
                        using (var notesReader = new BinaryReader(notesStream))
                        {
                            BuildId buildId = NoteSection.ReadBuildId(notesReader, size);
                            if (buildId != BuildId.Empty)
                            {
                                return(new DumpModule(file.Path, buildId,
                                                      moduleHeader.IsExecutable));
                            }
                        }
                    }
                }
            }

            return(DumpModule.Empty);
        }