mirror of
https://github.com/LukeFZ/Il2CppInspectorRedux.git
synced 2026-03-22 00:18:18 +05:00
add support for relr relocations in nso loader
This commit is contained in:
@@ -136,6 +136,9 @@ public enum DynamicTag : long
|
|||||||
DT_SYMENT = 0xb,
|
DT_SYMENT = 0xb,
|
||||||
DT_INIT = 0xC,
|
DT_INIT = 0xC,
|
||||||
DT_FINI = 0xD,
|
DT_FINI = 0xD,
|
||||||
|
DT_SONAME = 0xe,
|
||||||
|
DT_RPATH = 0xf,
|
||||||
|
DT_SYMBOLIC = 0x10,
|
||||||
DT_REL = 0x11,
|
DT_REL = 0x11,
|
||||||
DT_RELSZ = 0x12,
|
DT_RELSZ = 0x12,
|
||||||
DT_RELENT = 0x13,
|
DT_RELENT = 0x13,
|
||||||
@@ -152,11 +155,19 @@ public enum DynamicTag : long
|
|||||||
DT_FLAGS = 0x1E,
|
DT_FLAGS = 0x1E,
|
||||||
DT_PREINIT_ARRAY = 0x20,
|
DT_PREINIT_ARRAY = 0x20,
|
||||||
DT_PREINIT_ARRAYSZ = 0x21,
|
DT_PREINIT_ARRAYSZ = 0x21,
|
||||||
|
DT_MAXPOSTAGS = 0x22,
|
||||||
|
DT_RELRSZ = 0x23,
|
||||||
|
DT_RELR = 0x24,
|
||||||
|
DT_RELRENT = 0x25,
|
||||||
DT_LOOS = 0x6000000D,
|
DT_LOOS = 0x6000000D,
|
||||||
DT_ANDROID_REL = DT_LOOS + 2,
|
DT_ANDROID_REL = DT_LOOS + 2,
|
||||||
DT_ANDROID_RELSZ = DT_LOOS + 3,
|
DT_ANDROID_RELSZ = DT_LOOS + 3,
|
||||||
DT_ANDROID_RELA = DT_LOOS + 4,
|
DT_ANDROID_RELA = DT_LOOS + 4,
|
||||||
DT_ANDROID_RELASZ = DT_LOOS + 5
|
DT_ANDROID_RELASZ = DT_LOOS + 5,
|
||||||
|
DT_ANDROID_RELR = 0x6fffe000,
|
||||||
|
DT_ANDROID_RELRSZ = 0x6fffe001,
|
||||||
|
DT_ANDROID_RELRENT = 0x6fffe003,
|
||||||
|
DT_ANDROID_RELRCOUNT = 0x6fffe005,
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SymbolEntry : IReadable
|
public struct SymbolEntry : IReadable
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ using System.Collections.Frozen;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using VersionedSerialization;
|
using VersionedSerialization;
|
||||||
|
|
||||||
namespace Il2CppInspector;
|
namespace Il2CppInspector;
|
||||||
@@ -84,6 +86,17 @@ internal class ByteArrayBackingBuffer : IDisposable
|
|||||||
.ReadPrimitive<T>();
|
.ReadPrimitive<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImmutableArray<T> ReadPrimitiveArray<T>(ulong address, long count) where T : unmanaged
|
||||||
|
{
|
||||||
|
Debug.Assert(Initialized);
|
||||||
|
|
||||||
|
return IsLittleEndian
|
||||||
|
? Reader.LittleEndian(Data, TranslateVaToRva(address), new ReaderConfig(Is32Bit))
|
||||||
|
.ReadPrimitiveArray<T>(count)
|
||||||
|
: Reader.BigEndian(Data, TranslateVaToRva(address), new ReaderConfig(Is32Bit))
|
||||||
|
.ReadPrimitiveArray<T>(count);
|
||||||
|
}
|
||||||
|
|
||||||
public void WriteNUInt(ulong address, ulong value)
|
public void WriteNUInt(ulong address, ulong value)
|
||||||
{
|
{
|
||||||
var region = Data.Slice(TranslateVaToRva(address), Is32Bit ? sizeof(uint) : sizeof(ulong));
|
var region = Data.Slice(TranslateVaToRva(address), Is32Bit ? sizeof(uint) : sizeof(ulong));
|
||||||
@@ -269,6 +282,13 @@ public class NsoReader : FileFormatStream<NsoReader>
|
|||||||
relocationRegions.Add((jmprelAddress, jmprelAddress + size));
|
relocationRegions.Add((jmprelAddress, jmprelAddress + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dynamicEntries.TryGetValue(DynamicTag.DT_RELR, out var relrAddress))
|
||||||
|
{
|
||||||
|
var size = _dynamicEntries[DynamicTag.DT_RELRSZ];
|
||||||
|
ApplyRelrRelocations(relrAddress, size);
|
||||||
|
relocationRegions.Add((relrAddress, relrAddress + size));
|
||||||
|
}
|
||||||
|
|
||||||
_relocationEntryRegions = [.. relocationRegions];
|
_relocationEntryRegions = [.. relocationRegions];
|
||||||
|
|
||||||
// Clear out relocation sections in memory so searching is faster
|
// Clear out relocation sections in memory so searching is faster
|
||||||
@@ -339,6 +359,64 @@ public class NsoReader : FileFormatStream<NsoReader>
|
|||||||
return [.. _mappedExecutable.ReadObjectArray<RelaEntry>(ImageBase + rva, checked((int)entryCount), default)
|
return [.. _mappedExecutable.ReadObjectArray<RelaEntry>(ImageBase + rva, checked((int)entryCount), default)
|
||||||
.Select<RelaEntry, (ulong, ulong, long?)>(x => (x.Offset, x.Info, x.Addend))];
|
.Select<RelaEntry, (ulong, ulong, long?)>(x => (x.Offset, x.Info, x.Addend))];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyRelrRelocations(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
if (Is32Bit)
|
||||||
|
{
|
||||||
|
ApplyRelrRelocationsImpl<uint>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyRelrRelocationsImpl<ulong>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
void ApplyRelrRelocationsImpl<T>() where T : unmanaged, IUnsignedNumber<T>, IBinaryNumber<T>
|
||||||
|
{
|
||||||
|
Debug.Assert(typeof(T) == typeof(uint) || typeof(T) == typeof(ulong));
|
||||||
|
|
||||||
|
var entrySize = _dynamicEntries[DynamicTag.DT_RELRENT];
|
||||||
|
var entryCount = size / entrySize;
|
||||||
|
Debug.Assert(entrySize == (uint)Unsafe.SizeOf<T>());
|
||||||
|
|
||||||
|
var relrWords = _mappedExecutable.ReadPrimitiveArray<T>(ImageBase + address, checked((int)entryCount));
|
||||||
|
|
||||||
|
var baseAddr = 0ul;
|
||||||
|
for (int i = 0; i < relrWords.Length; i++)
|
||||||
|
{
|
||||||
|
var word = ulong.CreateChecked(relrWords[i]);
|
||||||
|
ulong offset;
|
||||||
|
|
||||||
|
if ((word & 1) == 0)
|
||||||
|
{
|
||||||
|
offset = word;
|
||||||
|
var value = ulong.CreateChecked(_mappedExecutable.ReadPrimitive<T>(ImageBase + offset));
|
||||||
|
_mappedExecutable.WriteNUInt(ImageBase + offset, ImageBase + value);
|
||||||
|
baseAddr = offset + entrySize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = baseAddr;
|
||||||
|
while (word != 0)
|
||||||
|
{
|
||||||
|
word >>= 1;
|
||||||
|
|
||||||
|
if ((word & 1) != 0)
|
||||||
|
{
|
||||||
|
var value = ulong.CreateChecked(_mappedExecutable.ReadPrimitive<T>(ImageBase + offset));
|
||||||
|
_mappedExecutable.WriteNUInt(ImageBase + offset, ImageBase + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += entrySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseAddr += (8 * entrySize - 1) * entrySize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override uint[] GetFunctionTable() => [];
|
public override uint[] GetFunctionTable() => [];
|
||||||
@@ -352,6 +430,11 @@ public class NsoReader : FileFormatStream<NsoReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileOffset = checked((uint)(uiAddr - ImageBase));
|
fileOffset = checked((uint)(uiAddr - ImageBase));
|
||||||
|
if (fileOffset > Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user