/// <summary> /// Initializes a new instance of the <see cref="ElfFile"/> class. /// </summary> /// /// <param name="header"> /// The ELF file header. /// </param> /// /// <param name="segments"> /// The program header table. /// </param> /// /// <param name="sections"> /// The section header table. /// </param> internal ElfFile(ElfHeader header, ElfProgramHeaderTable segments, ElfSectionHeaderTable sections) { Header = header; Segments = segments; Sections = sections; }
/// <summary> /// Initializes a new instance of the <see cref="ElfProgramHeaderTable"/> class by examining an ELF header. /// </summary> /// /// <param name="reader"> /// The reader used to extract the data needed to parse the ELF file. /// </param> /// /// <param name="header"> /// The ELF header used to extract the metadata about this program header table. /// </param> /// /// <param name="sections"> /// The list of sections which will be parsed to extract the sections corresponding to this segment. /// </param> internal ElfProgramHeaderTable(BinaryReader reader, ElfHeader header, ElfSectionHeaderTable sections) { // Initialize all segments for (var i = 0; i < header.ProgramHeaderEntryCount; i++) { ElfSegment segment; switch (header.Class) { case ElfClass.Elf32: { segment = new Bit32.ElfSegment(reader, (long)(header.ProgramHeaderOffset + (ulong)(i * header.ProgramHeaderSize))); break; } case ElfClass.Elf64: { segment = new Bit64.ElfSegment(reader, (long)(header.ProgramHeaderOffset + (ulong)(i * header.ProgramHeaderSize))); break; } default: { throw new InvalidOperationException("Unreachable case reached"); } } segment.Sections = sections.Where(s => s.Address >= segment.VirtualAddress && s.Address < segment.VirtualAddress + segment.MemorySize).ToList().AsReadOnly(); segments.Add(segment); } }
/// <summary> /// Initializes a new instance of the <see cref="ElfSectionHeaderTable"/> class by examining an ELF header. /// </summary> /// /// <param name="reader"> /// The reader used to extract the data needed to parse the ELF file. /// </param> /// /// <param name="header"> /// The ELF header used to extract the metadata about this section header table. /// </param> internal ElfSectionHeaderTable(BinaryReader reader, ElfHeader header) { // Initialize all segments for (var i = 0; i < header.SectionHeaderEntryCount; ++i) { ElfSection section; switch (header.Class) { case ElfClass.Elf32: { section = new Bit32.ElfSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); switch (section.Type) { case ElfSectionType.Dynamic: { section = new Bit32.ElfDynamicSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.DynSym: case ElfSectionType.SymTab: { section = new Bit32.ElfSymbolTable(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.Rel: case ElfSectionType.RelA: { section = new Bit32.ElfRelocationSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.StrTab: { section = new Bit32.ElfStringTable(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } } break; } case ElfClass.Elf64: { section = new Bit64.ElfSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); switch (section.Type) { case ElfSectionType.Dynamic: { section = new Bit64.ElfDynamicSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.DynSym: case ElfSectionType.SymTab: { section = new Bit64.ElfSymbolTable(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.Rel: case ElfSectionType.RelA: { section = new Bit64.ElfRelocationSection(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } case ElfSectionType.StrTab: { section = new Bit64.ElfStringTable(reader, (long)(header.SectionHeaderOffset + (ulong)(i * header.SectionHeaderSize))); break; } } break; } default: { throw new InvalidOperationException("Unreachable case reached"); } } sections.Add(section); } ushort shStrIndex = header.StringSectionIndex; if (shStrIndex != (ushort)ElfSectionType.Null) { // Initialize section names for (var i = 0; i < header.SectionHeaderEntryCount; i++) { sections[i].Name = reader.ReadELFString(this[shStrIndex], this[i].NameOffset); } } // Parse all dynamic entries names now that we have all sections initalized foreach (ElfDynamicSection dynamicSection in sections.OfType <ElfDynamicSection>()) { ElfDynamicEntry strTab = dynamicSection.FirstOrDefault(e => e.Tag == ElfDynamicArrayTag.StrTab); if (strTab != null) { ElfSection dynSymSection = sections.First(s => s.Address == strTab.Value); foreach (ElfDynamicEntry entry in dynamicSection) { switch (entry.Tag) { case ElfDynamicArrayTag.Needed: case ElfDynamicArrayTag.SOName: case ElfDynamicArrayTag.RPath: case ElfDynamicArrayTag.RunPath: { entry.Name = reader.ReadELFString(dynSymSection, entry.Value); break; } } } } } var symTab = sections.OfType <ElfSymbolTable>().FirstOrDefault(); if (symTab != null) { var strTab = sections[(int)symTab.Link]; if (strTab is ElfStringTable) { // Parse all relocation entries symbols now that we have all sections initalized foreach (ElfSymbolTableEntry entry in symTab) { entry.Name = reader.ReadELFString(strTab, entry.NameIndex); } // Parse all relocation entries symbols now that we have all sections initalized foreach (ElfRelocationSection relocationSection in sections.OfType <ElfRelocationSection>()) { foreach (ElfRelocationEntry entry in relocationSection) { entry.Symbol = symTab[entry.SymbolIndex].Name; entry.SymbolValue = symTab[entry.SymbolIndex].Value; } } } } }