Skip to content

Commit

Permalink
Huge speed improvement for 32-bit games.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Byass committed Jan 22, 2021
1 parent 52d8e71 commit f0c6cae
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
1 change: 0 additions & 1 deletion Cpp2IL/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace Cpp2IL
{
public static class Extensions
{
public static bool IsImmediate(this OpKind opKind) => opKind >= OpKind.Immediate8 && opKind <= OpKind.Immediate32to64;
public static T[] SubArray<T>(this T[] data, int index, int length)
{
var result = new T[length];
Expand Down
1 change: 1 addition & 0 deletions LibCpp2IL/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace LibCpp2IL
{
public static class Extensions
{
public static bool IsImmediate(this OpKind opKind) => opKind >= OpKind.Immediate8 && opKind <= OpKind.Immediate32to64;
public static ulong GetRipBasedInstructionMemoryAddress(this Instruction instruction) => instruction.NextIP + instruction.MemoryDisplacement64;

public static T[] SubArray<T>(this T[] data, int index, int length)
Expand Down
25 changes: 19 additions & 6 deletions LibCpp2IL/PE/PE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public bool PlusSearch(int methodCount, int typeDefinitionsCount)
}
}

ulong codeRegistration;
ulong codeRegistration = 0;
ulong metadataRegistration;

Console.WriteLine("Attempting to locate code and metadata registration functions...");
Expand All @@ -353,11 +353,24 @@ public bool PlusSearch(int methodCount, int typeDefinitionsCount)
plusSearch.SetExecSections(imageBase, dataSections);
metadataRegistration = plusSearch.FindMetadataRegistration64Bit();
}

if (LibCpp2IlMain.MetadataVersion >= 24.2f)
codeRegistration = plusSearch.FindCodeRegistrationUsingMscorlib();
else
codeRegistration = is32Bit ? plusSearch.FindCodeRegistration() : plusSearch.FindCodeRegistration64Bit();

if (is32Bit && metadataRegistration != 0)
{
codeRegistration = plusSearch.TryFindCodeRegUsingMetaReg(metadataRegistration);
}

if (codeRegistration == 0)
{
if (LibCpp2IlMain.MetadataVersion >= 24.2f)
{
Console.WriteLine("\tUsing mscorlib full-disassembly approach to get codereg, this may take a while...");
codeRegistration = plusSearch.FindCodeRegistrationUsingMscorlib();
}
else
codeRegistration = is32Bit ? plusSearch.FindCodeRegistration() : plusSearch.FindCodeRegistration64Bit();
}



#if ALLOW_CODEREG_FALLBACK
if (codeRegistration == 0 || metadataRegistration == 0)
Expand Down
23 changes: 21 additions & 2 deletions LibCpp2IL/PlusSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,25 @@ private IEnumerable<ulong> FindAllMappedWords(ulong va)
// Find all valid virtual address pointers to a set of virtual addresses
private IEnumerable<ulong> FindAllMappedWords(IEnumerable<ulong> va) => va.SelectMany(FindAllMappedWords);

public ulong TryFindCodeRegUsingMetaReg(ulong metadataRegistration)
{
var textSection = _pe.sections.First(s => s.Name == ".text");
var toDisasm = _pe.raw.SubArray((int) textSection.PointerToRawData, (int) textSection.SizeOfRawData);
var allInstructions = LibCpp2ILUtils.DisassembleBytesNew(_pe.is32Bit, toDisasm, textSection.VirtualAddress + _pe.imageBase);

var pushMetaReg = allInstructions.FirstOrDefault(i => i.Mnemonic == Mnemonic.Push && i.Op0Kind.IsImmediate() && i.GetImmediate(0) == metadataRegistration);
if (pushMetaReg.Mnemonic == Mnemonic.Push) //Check non-default.
{
var idx = allInstructions.IndexOf(pushMetaReg);
//Code reg has to be pushed after meta reg, cause that's how functions are called on 32-bit stdcall.
var hopefullyPushCodeReg = allInstructions[idx + 1];
if (hopefullyPushCodeReg.Mnemonic == Mnemonic.Push && hopefullyPushCodeReg.Op0Kind.IsImmediate())
return hopefullyPushCodeReg.GetImmediate(0);
}

return 0;
}

internal ulong FindCodeRegistrationUsingMscorlib()
{
//Works only on >=24.2
Expand Down Expand Up @@ -197,7 +216,7 @@ internal ulong FindCodeRegistrationUsingMscorlib()
if (sanity++ > 500) break;

endOfCodeGenRegAddr = endOfCodeGenRegAddr.Select(va => va - 4);
codeRegVas = FindAllMappedWords(endOfCodeGenRegAddr);
codeRegVas = FindAllMappedWords(endOfCodeGenRegAddr).AsParallel().ToList();
}

if (endOfCodeGenRegAddr.Count() != 1)
Expand All @@ -206,7 +225,7 @@ internal ulong FindCodeRegistrationUsingMscorlib()
return endOfCodeGenRegAddr.First();
}
}

private ulong FindCodeRegistration64BitPost2019()
{
//NOTE: With 64-bit ELF binaries we should iterate on exec, on everything else data.
Expand Down

0 comments on commit f0c6cae

Please sign in to comment.