Implement mapping from file offset to virtual address (all file formats)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user