Implement mapping from file offset to virtual address (all file formats)

This commit is contained in:
Katy Coe
2020-07-27 21:10:59 +02:00
parent 8b2c254235
commit 613747fc9a
6 changed files with 71 additions and 11 deletions

View File

@@ -1,6 +1,6 @@
/*
Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -110,6 +110,7 @@ namespace Il2CppInspector
private elf_dynamic<TWord>[] dynamic_table;
private elf_header<TWord> elf_header;
private Dictionary<string, elf_shdr<TWord>> sectionByName = new Dictionary<string, elf_shdr<TWord>>();
private List<(uint Start, uint End)> reverseMapExclusions = new List<(uint Start, uint End)>();
public ElfReader(Stream stream) : base(stream) { }
@@ -177,28 +178,38 @@ namespace Il2CppInspector
StatusUpdate("Processing relocations");
// Two types: add value from offset in image, and add value from specified addend
foreach (var relSection in getSections(Elf.SHT_REL))
foreach (var relSection in getSections(Elf.SHT_REL)) {
reverseMapExclusions.Add(((uint) conv.Int(relSection.sh_offset), (uint) (conv.Int(relSection.sh_offset) + conv.Int(relSection.sh_size) - 1)));
rels.UnionWith(
from rel in ReadArray<elf_rel<TWord>>(conv.Long(relSection.sh_offset), conv.Int(conv.Div(relSection.sh_size, relSection.sh_entsize)))
select new ElfReloc(rel, section_header_table[relSection.sh_link].sh_offset));
foreach (var relaSection in getSections(Elf.SHT_RELA))
}
foreach (var relaSection in getSections(Elf.SHT_RELA)) {
reverseMapExclusions.Add(((uint) conv.Int(relaSection.sh_offset), (uint) (conv.Int(relaSection.sh_offset) + conv.Int(relaSection.sh_size) - 1)));
rels.UnionWith(
from rela in ReadArray<elf_rela<TWord>>(conv.Long(relaSection.sh_offset), conv.Int(conv.Div(relaSection.sh_size, relaSection.sh_entsize)))
select new ElfReloc(rela, section_header_table[relaSection.sh_link].sh_offset));
}
// Relocations in dynamic section
if (getDynamic(Elf.DT_REL) is elf_dynamic<TWord> dt_rel) {
var dt_rel_count = conv.Div(getDynamic(Elf.DT_RELSZ).d_un, getDynamic(Elf.DT_RELENT).d_un);
var dt_rel_list = ReadArray<elf_rel<TWord>>(MapVATR(conv.ULong(dt_rel.d_un)), conv.Int(dt_rel_count));
var dt_rel_count = conv.Int(conv.Div(getDynamic(Elf.DT_RELSZ).d_un, getDynamic(Elf.DT_RELENT).d_un));
var dt_item_size = Sizeof(typeof(elf_rel<TWord>));
var dt_start = MapVATR(conv.ULong(dt_rel.d_un));
var dt_rel_list = ReadArray<elf_rel<TWord>>(dt_start, dt_rel_count);
var dt_symtab = getDynamic(Elf.DT_SYMTAB).d_un;
reverseMapExclusions.Add((dt_start, (uint) (dt_start + dt_rel_count * dt_item_size - 1)));
rels.UnionWith(from rel in dt_rel_list select new ElfReloc(rel, dt_symtab));
}
if (getDynamic(Elf.DT_RELA) is elf_dynamic<TWord> dt_rela) {
var dt_rela_count = conv.Div(getDynamic(Elf.DT_RELASZ).d_un, getDynamic(Elf.DT_RELAENT).d_un);
var dt_rela_list = ReadArray<elf_rela<TWord>>(MapVATR(conv.ULong(dt_rela.d_un)), conv.Int(dt_rela_count));
var dt_rela_count = conv.Int(conv.Div(getDynamic(Elf.DT_RELASZ).d_un, getDynamic(Elf.DT_RELAENT).d_un));
var dt_item_size = Sizeof(typeof(elf_rela<TWord>));
var dt_start = MapVATR(conv.ULong(dt_rela.d_un));
var dt_rela_list = ReadArray<elf_rela<TWord>>(dt_start, dt_rela_count);
var dt_symtab = getDynamic(Elf.DT_SYMTAB).d_un;
reverseMapExclusions.Add((dt_start, (uint) (dt_start + dt_rela_count * dt_item_size - 1)));
rels.UnionWith(from rela in dt_rela_list select new ElfReloc(rela, dt_symtab));
}
@@ -391,6 +402,15 @@ namespace Il2CppInspector
var program_header_table = this.program_header_table.First(x => uiAddr >= conv.ULong(x.p_vaddr) && uiAddr <= conv.ULong(conv.Add(x.p_vaddr, x.p_filesz)));
return (uint) (uiAddr - conv.ULong(conv.Sub(program_header_table.p_vaddr, program_header_table.p_offset)));
}
public override ulong MapFileOffsetToVA(uint offset) {
// Exclude relocation areas
if (reverseMapExclusions.Any(r => offset >= r.Start && offset <= r.End))
throw new InvalidOperationException("Attempt to map to a relocation address");
var section = program_header_table.First(x => offset >= conv.Int(x.p_offset) && offset < conv.Int(x.p_offset) + conv.Int(x.p_filesz));
return conv.ULong(section.p_vaddr) + offset - conv.ULong(section.p_offset);
}
// Get the address of the procedure linkage table (.got.plt) which is needed for some disassemblies
public uint GetPLTAddress() => (uint) conv.ULong(getDynamic(Elf.DT_PLTGOT).d_un);

View File

@@ -35,6 +35,8 @@ namespace Il2CppInspector
long[] ReadMappedWordArray(ulong uiAddr, int count);
uint MapVATR(ulong uiAddr);
bool TryMapVATR(ulong uiAddr, out uint fileOffset);
ulong MapFileOffsetToVA(uint offset);
bool TryMapFileOffsetToVA(uint offset, out ulong va);
byte[] ReadBytes(int count);
ulong ReadUInt64();
@@ -159,6 +161,22 @@ namespace Il2CppInspector
}
}
// Map an offset into the file image to an RVA
// No mapping by default
public virtual ulong MapFileOffsetToVA(uint offset) => offset;
// Try to map an offset into the file image to an RVA
public bool TryMapFileOffsetToVA(uint offset, out ulong va) {
try {
va = MapFileOffsetToVA(offset);
return true;
}
catch (InvalidOperationException) {
va = 0;
return false;
}
}
// Read a file format dependent word (32 or 64 bits)
// The primitive mappings in Bin2Object will automatically read a uint if the file is 32-bit
public long ReadWord() => ReadObject<long>();

View File

@@ -1,6 +1,6 @@
/*
Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -30,6 +30,7 @@ namespace Il2CppInspector
ET_EXEC = 2,
// PHTs
PT_LOAD = 1,
PT_DYNAMIC = 2,
DT_PLTGOT = 3,

View File

@@ -27,6 +27,11 @@ namespace Il2CppInspector
var section = sections.First(x => uiAddr >= x.Address && uiAddr <= x.Address + x.Size);
return (uint) uiAddr - (section.Address - section.ImageOffset);
}
public override ulong MapFileOffsetToVA(uint offset) {
var section = sections.First(x => offset >= x.ImageOffset && offset < x.ImageOffset + x.Size);
return section.Address + offset - section.ImageOffset;
}
}
internal class MachOReader64 : MachOReader<ulong, MachOReader64, Convert64>
@@ -44,6 +49,11 @@ namespace Il2CppInspector
var section = sections.First(x => uiAddr >= x.Address && uiAddr <= x.Address + x.Size);
return (uint) (uiAddr - (section.Address - section.ImageOffset));
}
public override ulong MapFileOffsetToVA(uint offset) {
var section = sections.First(x => offset >= x.ImageOffset && offset < x.ImageOffset + x.Size);
return section.Address + offset - section.ImageOffset;
}
}
// We need this convoluted generic TReader declaration so that "static T FileFormatReader.Load(Stream)"

View File

@@ -1,5 +1,5 @@
/*
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -150,5 +150,11 @@ namespace Il2CppInspector
uiAddr - pe.ImageBase < x.VirtualAddress + x.SizeOfRawData);
return (uint) (uiAddr - section.VirtualAddress - pe.ImageBase + section.PointerToRawData);
}
public override ulong MapFileOffsetToVA(uint offset) {
var section = sections.First(x => offset >= x.PointerToRawData && offset < x.PointerToRawData + x.SizeOfRawData);
return pe.ImageBase + section.VirtualAddress + offset - section.PointerToRawData;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -119,5 +119,10 @@ namespace Il2CppInspector
var program_header_table = pht.First(x => uiAddr >= x.p_vaddr && uiAddr <= x.p_vaddr + x.p_filesz);
return (uint) (uiAddr - (program_header_table.p_vaddr - program_header_table.p_offset));
}
public override ulong MapFileOffsetToVA(uint offset) {
var segment = pht.First(x => offset >= x.p_offset && offset < x.p_offset + x.p_filesz);
return segment.p_vaddr + offset - segment.p_offset;
}
}
}