From 538e51ac29ee8abf3fa739dd4262c0a9be7c5bf0 Mon Sep 17 00:00:00 2001
From: ds5678 <49847914+ds5678@users.noreply.github.com>
Date: Sun, 8 Sep 2024 10:27:14 -0700
Subject: [PATCH 1/2] Port UnhollowerPdbGen to Il2CppInterop
---
.../Il2CppInterop.Pdb.Generator.csproj | 17 ++
.../MethodAddressToTokenMap.cs | 29 ++++
Il2CppInterop.Pdb.Generator/MsPdbCore.cs | 157 ++++++++++++++++++
Il2CppInterop.Pdb.Generator/Program.cs | 101 +++++++++++
Il2CppInterop.Pdb.Generator/README.md | 17 ++
Il2CppInterop.sln | 24 ++-
6 files changed, 336 insertions(+), 9 deletions(-)
create mode 100644 Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
create mode 100644 Il2CppInterop.Pdb.Generator/MethodAddressToTokenMap.cs
create mode 100644 Il2CppInterop.Pdb.Generator/MsPdbCore.cs
create mode 100644 Il2CppInterop.Pdb.Generator/Program.cs
create mode 100644 Il2CppInterop.Pdb.Generator/README.md
diff --git a/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj b/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
new file mode 100644
index 00000000..fdb093bc
--- /dev/null
+++ b/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ Exe
+ Il2CppInterop.Pdb.Generator
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Il2CppInterop.Pdb.Generator/MethodAddressToTokenMap.cs b/Il2CppInterop.Pdb.Generator/MethodAddressToTokenMap.cs
new file mode 100644
index 00000000..a06323a0
--- /dev/null
+++ b/Il2CppInterop.Pdb.Generator/MethodAddressToTokenMap.cs
@@ -0,0 +1,29 @@
+using AsmResolver.DotNet;
+using Il2CppInterop.Common.Maps;
+
+#nullable enable
+
+namespace Il2CppInterop.Pdb.Generator;
+
+public class MethodAddressToTokenMap : MethodAddressToTokenMapBase
+{
+ public MethodAddressToTokenMap(string filePath) : base(filePath)
+ {
+ }
+
+ protected override AssemblyDefinition? LoadAssembly(string assemblyName)
+ {
+ var filesDirt = Path.GetDirectoryName(myFilePath)!;
+ assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(','));
+ return AssemblyDefinition.FromFile(Path.Combine(filesDirt, assemblyName + ".dll"));
+ }
+
+ protected override MethodDefinition? ResolveMethod(AssemblyDefinition? assembly, int token)
+ {
+ if (assembly?.ManifestModule?.TryLookupMember(token, out MethodDefinition? result) ?? false)
+ {
+ return result;
+ }
+ return null;
+ }
+}
diff --git a/Il2CppInterop.Pdb.Generator/MsPdbCore.cs b/Il2CppInterop.Pdb.Generator/MsPdbCore.cs
new file mode 100644
index 00000000..0f5c5821
--- /dev/null
+++ b/Il2CppInterop.Pdb.Generator/MsPdbCore.cs
@@ -0,0 +1,157 @@
+using System.Runtime.InteropServices;
+using System.Text;
+
+// Source/reference: https://github.com/microsoft/microsoft-pdb, MIT license
+namespace Il2CppInterop.Pdb.Generator;
+
+enum PDBErrors : int
+{
+ EC_OK, // no problem
+ EC_USAGE, // invalid parameter or call order
+ EC_OUT_OF_MEMORY, // out of heap
+ EC_FILE_SYSTEM, // "pdb name", can't write file, out of disk, etc.
+ EC_NOT_FOUND, // "pdb name", PDB file not found
+ EC_INVALID_SIG, // "pdb name", PDB::OpenValidate() and its clients only
+ EC_INVALID_AGE, // "pdb name", PDB::OpenValidate() and its clients only
+ EC_PRECOMP_REQUIRED, // "obj name", Mod::AddTypes() only
+ EC_OUT_OF_TI, // "pdb name", TPI::QueryTiForCVRecord() only
+ EC_NOT_IMPLEMENTED, // -
+ EC_V1_PDB, // "pdb name", PDB::Open* only (obsolete)
+ EC_UNKNOWN_FORMAT = EC_V1_PDB, // pdb can't be opened because it has newer versions of stuff
+ EC_FORMAT, // accessing pdb with obsolete format
+ EC_LIMIT,
+ EC_CORRUPT, // cv info corrupt, recompile mod
+ EC_TI16, // no 16-bit type interface present
+ EC_ACCESS_DENIED, // "pdb name", PDB file read-only
+ EC_ILLEGAL_TYPE_EDIT, // trying to edit types in read-only mode
+ EC_INVALID_EXECUTABLE, // not recogized as a valid executable
+ EC_DBG_NOT_FOUND, // A required .DBG file was not found
+ EC_NO_DEBUG_INFO, // No recognized debug info found
+ EC_INVALID_EXE_TIMESTAMP, // Invalid timestamp on Openvalidate of exe
+ EC_CORRUPT_TYPEPOOL, // A corrupted type record was found in a PDB
+ EC_DEBUG_INFO_NOT_IN_PDB, // returned by OpenValidateX
+ EC_RPC, // Error occured during RPC
+ EC_UNKNOWN, // Unknown error
+ EC_BAD_CACHE_PATH, // bad cache location specified with symsrv
+ EC_CACHE_FULL, // symsrv cache is full
+ EC_TOO_MANY_MOD_ADDTYPE, // Addtype is called more then once per mod
+ EC_MAX
+}
+
+[Flags]
+enum CV_PUBSYMFLAGS_e : int
+{
+ cvpsfNone = 0,
+ cvpsfCode = 0x00000001,
+ cvpsfFunction = 0x00000002,
+ cvpsfManaged = 0x00000004,
+ cvpsfMSIL = 0x00000008,
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct PdbPtr
+{
+ public IntPtr InnerPtr;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct DbiPtr
+{
+ public IntPtr InnerPtr;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct ModPtr
+{
+ public IntPtr InnerPtr;
+}
+
+public static unsafe class MsPdbCore
+{
+ private const string dllName = "mspdbcore.dll";
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PDBOpen2W(char* wszPDB, byte* szMode, out PDBErrors pec, char* wszError, nuint cchErrMax, out PdbPtr pppdb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PDBCommit(PdbPtr ppdb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PDBOpenDBI(PdbPtr ppdb, byte* szMode, byte* szTarget, out DbiPtr ppdbi);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool DBIOpenModW(DbiPtr pdbi, char* szModule, char* szFile, out ModPtr ppmod);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool DBIAddPublic2(DbiPtr pdbi, byte* szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool ModAddPublic2(ModPtr pmod, byte* szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool DBIAddSec(DbiPtr pdbi, ushort isect, ushort flags, int off, int cb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool ModClose(ModPtr ppdb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool DBIClose(DbiPtr ppdb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PDBClose(PdbPtr ppdb);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PDBQuerySignature2(PdbPtr ppdb, out Guid guid);
+
+ [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern uint PDBQueryAge(PdbPtr ppdb);
+
+
+ internal static bool PDBOpen2W(string wszPDB, string szMode, out PDBErrors pec, out string error, out PdbPtr pppdb)
+ {
+ wszPDB += '\0';
+ szMode += '\0';
+
+ var chars = wszPDB.ToCharArray();
+ var bytes = Encoding.UTF8.GetBytes(szMode);
+ var errorChars = new char[2048];
+ bool result = false;
+
+ fixed (char* cp = chars)
+ fixed (byte* bp = bytes)
+ fixed (char* ep = errorChars)
+ result = PDBOpen2W(cp, bp, out pec, ep, (nuint)errorChars.Length, out pppdb);
+
+ var firstZero = Array.IndexOf(errorChars, '\0');
+ error = new string(errorChars, 0, firstZero);
+
+ return result;
+ }
+
+ internal static bool PDBOpenDBI(PdbPtr ppdb, string szMode, string szTarget, out DbiPtr ppdbi)
+ {
+ szMode += '\0';
+ szTarget += '\0';
+
+ fixed (byte* mb = Encoding.UTF8.GetBytes(szMode))
+ fixed (byte* tb = Encoding.UTF8.GetBytes(szTarget))
+ return PDBOpenDBI(ppdb, mb, tb, out ppdbi);
+ }
+
+ internal static bool DBIOpenModW(DbiPtr pdbi, string szModule, string szFile, out ModPtr ppmod)
+ {
+ szFile += '\0';
+ szModule += '\0';
+
+ fixed (char* fp = szFile)
+ fixed (char* mp = szModule)
+ return DBIOpenModW(pdbi, mp, fp, out ppmod);
+ }
+
+ internal static bool ModAddPublic2(ModPtr pmod, string szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0)
+ {
+ szPublic += '\0';
+ fixed (byte* mb = Encoding.UTF8.GetBytes(szPublic))
+ return ModAddPublic2(pmod, mb, isect, off, cvpsf);
+ }
+}
diff --git a/Il2CppInterop.Pdb.Generator/Program.cs b/Il2CppInterop.Pdb.Generator/Program.cs
new file mode 100644
index 00000000..932eb181
--- /dev/null
+++ b/Il2CppInterop.Pdb.Generator/Program.cs
@@ -0,0 +1,101 @@
+using System.Reflection.PortableExecutable;
+
+namespace Il2CppInterop.Pdb.Generator;
+
+internal static class Program
+{
+ public static void Main(string[] args)
+ {
+ if (args.Length <= 1)
+ {
+ Console.WriteLine($"Usage: Il2CppInterop.Pdb.Generator.exe ");
+ }
+ var rootPath = Path.GetDirectoryName(args[0])!;
+ var map = new MethodAddressToTokenMap(args[1]);
+
+ using var peStream = new FileStream(args[0], FileMode.Open, FileAccess.Read);
+ using var peReader = new PEReader(peStream);
+
+
+ string openError;
+ PDBErrors err;
+ var pdbFilePath = Path.Combine(rootPath, "GameAssembly.pdb");
+ MsPdbCore.PDBOpen2W(pdbFilePath, "w", out err, out openError, out var pdb);
+
+ MsPdbCore.PDBOpenDBI(pdb, "w", "", out var dbi);
+
+ MsPdbCore.DBIOpenModW(dbi, "__Globals", "__Globals", out var mod);
+
+ ushort secNum = 1;
+ ushort i2cs = 1;
+ foreach (var sectionHeader in peReader.PEHeaders.SectionHeaders)
+ {
+ if (sectionHeader.Name == "il2cpp") i2cs = secNum;
+ MsPdbCore.DBIAddSec(dbi, secNum++, 0 /* TODO? */, sectionHeader.VirtualAddress, sectionHeader.VirtualSize);
+ }
+
+ foreach (var valueTuple in map)
+ {
+ ushort targetSect = 0;
+ long tsva = 0;
+ ushort sc = 1;
+ foreach (var sectionHeader in peReader.PEHeaders.SectionHeaders)
+ {
+ if (valueTuple.Item1 > sectionHeader.VirtualAddress)
+ {
+ targetSect = sc;
+ tsva = sectionHeader.VirtualAddress;
+ }
+ else
+ break;
+
+ sc++;
+ }
+
+ if (targetSect == 0) throw new ApplicationException("Bad segment");
+ MsPdbCore.ModAddPublic2(mod, valueTuple.Item2.FullName, targetSect, (int)(valueTuple.Item1 - tsva * 2), CV_PUBSYMFLAGS_e.cvpsfFunction);
+ }
+
+ MsPdbCore.ModClose(mod);
+ MsPdbCore.DBIClose(dbi);
+
+ MsPdbCore.PDBCommit(pdb);
+
+ MsPdbCore.PDBQuerySignature2(pdb, out var wrongGuid);
+
+ MsPdbCore.PDBClose(pdb);
+
+ // Hack: manually replace guid and age in generated .pdb, because there's no API on mspdbcore to set them manually
+ var targetDebugInfo = peReader.ReadCodeViewDebugDirectoryData(peReader.ReadDebugDirectory()
+ .Single(it => it.Type == DebugDirectoryEntryType.CodeView));
+
+ var wrongGuidBytes = wrongGuid.ToByteArray();
+ var allPdbBytes = File.ReadAllBytes(pdbFilePath);
+
+ var patchTarget = IndexOfBytes(allPdbBytes, wrongGuidBytes);
+ targetDebugInfo.Guid.TryWriteBytes(allPdbBytes.AsSpan(patchTarget));
+
+ Console.WriteLine(targetDebugInfo.Guid);
+ Console.WriteLine(targetDebugInfo.Age);
+
+ BitConverter.TryWriteBytes(allPdbBytes.AsSpan(patchTarget - 4), targetDebugInfo.Age);
+ File.WriteAllBytes(pdbFilePath, allPdbBytes);
+ }
+
+ private static int IndexOfBytes(byte[] haystack, byte[] needle)
+ {
+ for (var i = 0; i < haystack.Length - needle.Length; i++)
+ {
+ for (var j = 0; j < needle.Length; j++)
+ {
+ if (haystack[i + j] != needle[j])
+ goto moveOn;
+ }
+
+ return i;
+ moveOn:;
+ }
+
+ return -1;
+ }
+}
diff --git a/Il2CppInterop.Pdb.Generator/README.md b/Il2CppInterop.Pdb.Generator/README.md
new file mode 100644
index 00000000..70be3bb9
--- /dev/null
+++ b/Il2CppInterop.Pdb.Generator/README.md
@@ -0,0 +1,17 @@
+# PDB generator
+
+This is an executable that can be ran to generate a Microsoft PDB file (debug symbols) for GameAssembly.dll based on unhollower-generated names.
+
+This can be useful for analyzing code of obfuscated games. For unobfuscated games, using [Il2CppInspector](https://github.com/djkaty/Il2CppInspector) might provide better results for code analysis.
+
+Generated PDBs were tested with windbg, lldb, WPA viewer/ETL performance analysis and IDA.
+
+Generated PDBs only include generated methods, and don't include type info, generic method info and IL2CPP internals.
+
+You need to manually copy the following Microsoft-provided libraries from Visual Studio (or other build tools) for this to work. They cannot be redistributed because the license on them is not clear.
+
+ * `mspdbcore.dll`
+ * `msobj140.dll`
+ * `tbbmalloc.dll`
+
+These need to be placed next to the built executable file. Use file search to find `mspdbcore` in the Visual Studio install directory. By default, they are in `C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\`.
diff --git a/Il2CppInterop.sln b/Il2CppInterop.sln
index 80d120c6..a4aa5698 100644
--- a/Il2CppInterop.sln
+++ b/Il2CppInterop.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.31402.337
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35222.181
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Il2CppInterop.Generator", "Il2CppInterop.Generator\Il2CppInterop.Generator.csproj", "{7C3FD45B-A563-47AF-90DF-8B051A8C33A0}"
EndProject
@@ -10,9 +10,9 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{463B7E3B-94E8-4EEB-B54A-EF15AD9C7C7E}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
- README.md = README.md
- Directory.Build.props = Directory.Build.props
build.cake = build.cake
+ Directory.Build.props = Directory.Build.props
+ README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{99E71726-78FB-4376-89DA-90E5C08F5CD4}"
@@ -20,11 +20,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentat
Documentation\Class-Injection.md = Documentation\Class-Injection.md
Documentation\Command-Line-Usage.md = Documentation\Command-Line-Usage.md
Documentation\Common-Problems.md = Documentation\Common-Problems.md
- Documentation\Injected-Components-In-Asset-Bundles.md = Documentation\Injected-Components-In-Asset-Bundles.md
Documentation\Implementing-Interfaces.md = Documentation\Implementing-Interfaces.md
+ Documentation\Injected-Components-In-Asset-Bundles.md = Documentation\Injected-Components-In-Asset-Bundles.md
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInterop.CLI", "Il2CppInterop.CLI\Il2CppInterop.CLI.csproj", "{F5AA88D1-5E62-46B8-A11C-3FAC40C25600}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Il2CppInterop.CLI", "Il2CppInterop.CLI\Il2CppInterop.CLI.csproj", "{F5AA88D1-5E62-46B8-A11C-3FAC40C25600}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{771D8BE3-C373-4754-94EA-4A68B117BAEF}"
ProjectSection(SolutionItems) = preProject
@@ -32,11 +32,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{
.github\workflows\format_check.yml = .github\workflows\format_check.yml
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInterop.StructGenerator", "Il2CppInterop.StructGenerator\Il2CppInterop.StructGenerator.csproj", "{DE781BD4-650F-4ED8-B615-5CB36E6D476A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Il2CppInterop.StructGenerator", "Il2CppInterop.StructGenerator\Il2CppInterop.StructGenerator.csproj", "{DE781BD4-650F-4ED8-B615-5CB36E6D476A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Il2CppInterop.Common", "Il2CppInterop.Common\Il2CppInterop.Common.csproj", "{E7D3A81B-11CD-402C-A447-015B00DCA3FD}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInterop.Common", "Il2CppInterop.Common\Il2CppInterop.Common.csproj", "{E7D3A81B-11CD-402C-A447-015B00DCA3FD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Il2CppInterop.HarmonySupport", "Il2CppInterop.HarmonySupport\Il2CppInterop.HarmonySupport.csproj", "{EBC23884-3417-4F24-8623-E913C5151CC3}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInterop.HarmonySupport", "Il2CppInterop.HarmonySupport\Il2CppInterop.HarmonySupport.csproj", "{EBC23884-3417-4F24-8623-E913C5151CC3}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Il2CppInterop.Pdb.Generator", "Il2CppInterop.Pdb.Generator\Il2CppInterop.Pdb.Generator.csproj", "{55566454-FF96-4C35-9CF4-479F7130E4D1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -68,6 +70,10 @@ Global
{EBC23884-3417-4F24-8623-E913C5151CC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBC23884-3417-4F24-8623-E913C5151CC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBC23884-3417-4F24-8623-E913C5151CC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {55566454-FF96-4C35-9CF4-479F7130E4D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {55566454-FF96-4C35-9CF4-479F7130E4D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {55566454-FF96-4C35-9CF4-479F7130E4D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {55566454-FF96-4C35-9CF4-479F7130E4D1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
From a3065435702f35deff3214e4331824d7c441fea0 Mon Sep 17 00:00:00 2001
From: ds5678 <49847914+ds5678@users.noreply.github.com>
Date: Wed, 27 Nov 2024 15:29:59 -0800
Subject: [PATCH 2/2] Update to use AssetRipper.Bindings.MsPdbCore
---
.../Il2CppInterop.Pdb.Generator.csproj | 3 +-
Il2CppInterop.Pdb.Generator/MsPdbCore.cs | 157 ------------------
Il2CppInterop.Pdb.Generator/Program.cs | 7 +-
3 files changed, 6 insertions(+), 161 deletions(-)
delete mode 100644 Il2CppInterop.Pdb.Generator/MsPdbCore.cs
diff --git a/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj b/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
index fdb093bc..a064321a 100644
--- a/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
+++ b/Il2CppInterop.Pdb.Generator/Il2CppInterop.Pdb.Generator.csproj
@@ -1,13 +1,14 @@
- net6.0
+ net9.0
Exe
Il2CppInterop.Pdb.Generator
+
diff --git a/Il2CppInterop.Pdb.Generator/MsPdbCore.cs b/Il2CppInterop.Pdb.Generator/MsPdbCore.cs
deleted file mode 100644
index 0f5c5821..00000000
--- a/Il2CppInterop.Pdb.Generator/MsPdbCore.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-using System.Runtime.InteropServices;
-using System.Text;
-
-// Source/reference: https://github.com/microsoft/microsoft-pdb, MIT license
-namespace Il2CppInterop.Pdb.Generator;
-
-enum PDBErrors : int
-{
- EC_OK, // no problem
- EC_USAGE, // invalid parameter or call order
- EC_OUT_OF_MEMORY, // out of heap
- EC_FILE_SYSTEM, // "pdb name", can't write file, out of disk, etc.
- EC_NOT_FOUND, // "pdb name", PDB file not found
- EC_INVALID_SIG, // "pdb name", PDB::OpenValidate() and its clients only
- EC_INVALID_AGE, // "pdb name", PDB::OpenValidate() and its clients only
- EC_PRECOMP_REQUIRED, // "obj name", Mod::AddTypes() only
- EC_OUT_OF_TI, // "pdb name", TPI::QueryTiForCVRecord() only
- EC_NOT_IMPLEMENTED, // -
- EC_V1_PDB, // "pdb name", PDB::Open* only (obsolete)
- EC_UNKNOWN_FORMAT = EC_V1_PDB, // pdb can't be opened because it has newer versions of stuff
- EC_FORMAT, // accessing pdb with obsolete format
- EC_LIMIT,
- EC_CORRUPT, // cv info corrupt, recompile mod
- EC_TI16, // no 16-bit type interface present
- EC_ACCESS_DENIED, // "pdb name", PDB file read-only
- EC_ILLEGAL_TYPE_EDIT, // trying to edit types in read-only mode
- EC_INVALID_EXECUTABLE, // not recogized as a valid executable
- EC_DBG_NOT_FOUND, // A required .DBG file was not found
- EC_NO_DEBUG_INFO, // No recognized debug info found
- EC_INVALID_EXE_TIMESTAMP, // Invalid timestamp on Openvalidate of exe
- EC_CORRUPT_TYPEPOOL, // A corrupted type record was found in a PDB
- EC_DEBUG_INFO_NOT_IN_PDB, // returned by OpenValidateX
- EC_RPC, // Error occured during RPC
- EC_UNKNOWN, // Unknown error
- EC_BAD_CACHE_PATH, // bad cache location specified with symsrv
- EC_CACHE_FULL, // symsrv cache is full
- EC_TOO_MANY_MOD_ADDTYPE, // Addtype is called more then once per mod
- EC_MAX
-}
-
-[Flags]
-enum CV_PUBSYMFLAGS_e : int
-{
- cvpsfNone = 0,
- cvpsfCode = 0x00000001,
- cvpsfFunction = 0x00000002,
- cvpsfManaged = 0x00000004,
- cvpsfMSIL = 0x00000008,
-}
-
-[StructLayout(LayoutKind.Sequential)]
-public struct PdbPtr
-{
- public IntPtr InnerPtr;
-}
-
-[StructLayout(LayoutKind.Sequential)]
-public struct DbiPtr
-{
- public IntPtr InnerPtr;
-}
-
-[StructLayout(LayoutKind.Sequential)]
-public struct ModPtr
-{
- public IntPtr InnerPtr;
-}
-
-public static unsafe class MsPdbCore
-{
- private const string dllName = "mspdbcore.dll";
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool PDBOpen2W(char* wszPDB, byte* szMode, out PDBErrors pec, char* wszError, nuint cchErrMax, out PdbPtr pppdb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool PDBCommit(PdbPtr ppdb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool PDBOpenDBI(PdbPtr ppdb, byte* szMode, byte* szTarget, out DbiPtr ppdbi);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool DBIOpenModW(DbiPtr pdbi, char* szModule, char* szFile, out ModPtr ppmod);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool DBIAddPublic2(DbiPtr pdbi, byte* szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool ModAddPublic2(ModPtr pmod, byte* szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool DBIAddSec(DbiPtr pdbi, ushort isect, ushort flags, int off, int cb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool ModClose(ModPtr ppdb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool DBIClose(DbiPtr ppdb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool PDBClose(PdbPtr ppdb);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern bool PDBQuerySignature2(PdbPtr ppdb, out Guid guid);
-
- [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern uint PDBQueryAge(PdbPtr ppdb);
-
-
- internal static bool PDBOpen2W(string wszPDB, string szMode, out PDBErrors pec, out string error, out PdbPtr pppdb)
- {
- wszPDB += '\0';
- szMode += '\0';
-
- var chars = wszPDB.ToCharArray();
- var bytes = Encoding.UTF8.GetBytes(szMode);
- var errorChars = new char[2048];
- bool result = false;
-
- fixed (char* cp = chars)
- fixed (byte* bp = bytes)
- fixed (char* ep = errorChars)
- result = PDBOpen2W(cp, bp, out pec, ep, (nuint)errorChars.Length, out pppdb);
-
- var firstZero = Array.IndexOf(errorChars, '\0');
- error = new string(errorChars, 0, firstZero);
-
- return result;
- }
-
- internal static bool PDBOpenDBI(PdbPtr ppdb, string szMode, string szTarget, out DbiPtr ppdbi)
- {
- szMode += '\0';
- szTarget += '\0';
-
- fixed (byte* mb = Encoding.UTF8.GetBytes(szMode))
- fixed (byte* tb = Encoding.UTF8.GetBytes(szTarget))
- return PDBOpenDBI(ppdb, mb, tb, out ppdbi);
- }
-
- internal static bool DBIOpenModW(DbiPtr pdbi, string szModule, string szFile, out ModPtr ppmod)
- {
- szFile += '\0';
- szModule += '\0';
-
- fixed (char* fp = szFile)
- fixed (char* mp = szModule)
- return DBIOpenModW(pdbi, mp, fp, out ppmod);
- }
-
- internal static bool ModAddPublic2(ModPtr pmod, string szPublic, ushort isect, int off, CV_PUBSYMFLAGS_e cvpsf = 0)
- {
- szPublic += '\0';
- fixed (byte* mb = Encoding.UTF8.GetBytes(szPublic))
- return ModAddPublic2(pmod, mb, isect, off, cvpsf);
- }
-}
diff --git a/Il2CppInterop.Pdb.Generator/Program.cs b/Il2CppInterop.Pdb.Generator/Program.cs
index 932eb181..0727db5f 100644
--- a/Il2CppInterop.Pdb.Generator/Program.cs
+++ b/Il2CppInterop.Pdb.Generator/Program.cs
@@ -1,8 +1,9 @@
-using System.Reflection.PortableExecutable;
+using AssetRipper.Bindings.MsPdbCore;
+using System.Reflection.PortableExecutable;
namespace Il2CppInterop.Pdb.Generator;
-internal static class Program
+internal static unsafe class Program
{
public static void Main(string[] args)
{
@@ -53,7 +54,7 @@ public static void Main(string[] args)
}
if (targetSect == 0) throw new ApplicationException("Bad segment");
- MsPdbCore.ModAddPublic2(mod, valueTuple.Item2.FullName, targetSect, (int)(valueTuple.Item1 - tsva * 2), CV_PUBSYMFLAGS_e.cvpsfFunction);
+ MsPdbCore.ModAddPublic2(mod, valueTuple.Item2.FullName, targetSect, (int)(valueTuple.Item1 - tsva * 2), CV_PUBSYMFLAGS_e.Function);
}
MsPdbCore.ModClose(mod);