internal ElfFile(IElfHeader header, Reader reader, long position = 0, bool virt = false) { _reader = reader; _position = position; _virtual = virt; if (virt) { _virtualAddressReader = reader; } Header = header; }
internal ElfFile(IElfHeader header, Reader reader, long position = 0, bool isVirtual = false) { _reader = reader; _position = position; _virtual = isVirtual; if (isVirtual) { _virtualAddressReader = reader; } Header = header; }
internal override unsafe bool GetFileVersion(string dll, out int major, out int minor, out int revision, out int patch) { using FileStream stream = File.OpenRead(dll); StreamAddressSpace streamAddressSpace = new StreamAddressSpace(stream); Reader streamReader = new Reader(streamAddressSpace); ElfFile file = new ElfFile(streamReader); IElfHeader header = file.Header; ElfSectionHeader headerStringHeader = new ElfSectionHeader(streamReader, header.Is64Bit, header.SectionHeaderOffset + header.SectionHeaderStringIndex * header.SectionHeaderEntrySize); long headerStringOffset = (long)headerStringHeader.FileOffset; long dataOffset = 0; long dataSize = 0; for (int i = 0; i < header.SectionHeaderCount; i++) { if (i == header.SectionHeaderStringIndex) { continue; } ElfSectionHeader sectionHeader = new ElfSectionHeader(streamReader, header.Is64Bit, header.SectionHeaderOffset + i * header.SectionHeaderEntrySize); if (sectionHeader.Type == ElfSectionHeaderType.ProgBits) { string sectionName = streamReader.ReadNullTerminatedAscii(headerStringOffset + sectionHeader.NameIndex * sizeof(byte)); if (sectionName == ".data") { dataOffset = (long)sectionHeader.FileOffset; dataSize = (long)sectionHeader.FileSize; break; } } } DebugOnly.Assert(dataOffset != 0); DebugOnly.Assert(dataSize != 0); Span <byte> buffer = stackalloc byte[s_versionLength]; long address = dataOffset; long endAddress = address + dataSize; while (address < endAddress) { int read = streamAddressSpace.Read(address, buffer); if (read < s_versionLength) { break; } if (!buffer.SequenceEqual(s_versionString)) { address++; continue; } address += s_versionLength; // TODO: This should be cleaned up to not read byte by byte in the future. Leaving it here // until we decide whether to rewrite the Linux coredumpreader or not. StringBuilder builder = new StringBuilder(); while (address < endAddress) { Span <byte> bytes = stackalloc byte[1]; read = streamAddressSpace.Read(address, bytes); if (read < bytes.Length) { break; } if (bytes[0] == '\0') { break; } if (bytes[0] == ' ') { try { Version v = Version.Parse(builder.ToString()); major = v.Major; minor = v.Minor; revision = v.Build; patch = v.Revision; return(true); } catch (FormatException) { break; } } Span <char> chars = stackalloc char[1]; fixed(byte *bytesPtr = &MemoryMarshal.GetReference(bytes)) fixed(char *charsPtr = &MemoryMarshal.GetReference(chars)) { _ = Encoding.ASCII.GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length); } _ = builder.Append(chars[0]); address++; } break; } major = minor = revision = patch = 0; return(false); }