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)); }
/// <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); }