C++: Output il2cpp-api-functions.h with unavailable exports elided

This commit is contained in:
Katy Coe
2020-07-24 17:20:37 +02:00
parent 9966af0e73
commit 44a5fe009a
2 changed files with 32 additions and 4 deletions

View File

@@ -173,11 +173,15 @@ namespace Il2CppInspector.Cpp.UnityHeaders
} }
// Convert il2cpp-api-functions.h from "DO_API(r, n, p)" to "typedef r (*n)(p)" // Convert il2cpp-api-functions.h from "DO_API(r, n, p)" to "typedef r (*n)(p)"
internal static string GetTypedefsFromAPIHeader(string text) { private static readonly Regex APILineRegex = new Regex(@"^DO_API(?:_NO_RETURN)?\((.*?),(.*?),\s*\((.*?)\)\s*\);", RegexOptions.Multiline);
var rgx = new Regex(@"^DO_API(?:_NO_RETURN)?\((.*?),(.*?),\s*\((.*?)\)\s*\);", RegexOptions.Multiline);
return rgx.Replace(text, "typedef $1 (*$2)($3);"); internal static string GetFunctionNameFromAPILine(string line) {
var match = APILineRegex.Match(line);
return match.Success ? match.Groups[2].ToString().Trim() : string.Empty;
} }
internal static string GetTypedefsFromAPIHeader(string text) => APILineRegex.Replace(text, "typedef $1 (*$2)($3);");
// Get a list of function names from il2cpp-api-functions.h, taking #ifs into account // Get a list of function names from il2cpp-api-functions.h, taking #ifs into account
private static IEnumerable<string> GetFunctionNamesFromAPIHeaderText(string text) { private static IEnumerable<string> GetFunctionNamesFromAPIHeaderText(string text) {
var defText = GetTypedefsFromAPIHeader(text); var defText = GetTypedefsFromAPIHeader(text);

View File

@@ -9,6 +9,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Il2CppInspector.Reflection; using Il2CppInspector.Reflection;
using Il2CppInspector.Cpp; using Il2CppInspector.Cpp;
using Il2CppInspector.Cpp.UnityHeaders;
using Il2CppInspector.Model; using Il2CppInspector.Model;
using Il2CppInspector.Properties; using Il2CppInspector.Properties;
@@ -50,6 +51,27 @@ namespace Il2CppInspector.Outputs
writer.Close(); writer.Close();
// Write selected Unity API function file to il2cpp-api-functions.h
// (this is a copy of the header file from an actual Unity install)
var il2cppApiFile = Path.Combine(outputPath, "il2cpp-api-functions.h");
var apiHeaderText = model.UnityHeaders.GetAPIHeaderText();
using var fsApi = new FileStream(il2cppApiFile, FileMode.Create);
writer = new StreamWriter(fsApi, Encoding.UTF8);
writeHeader();
// Elide APIs that aren't in the binary to avoid compile errors
foreach (var line in apiHeaderText.Split('\n')) {
var fnName = UnityHeaders.GetFunctionNameFromAPILine(line);
if (string.IsNullOrEmpty(fnName))
writer.WriteLine(line);
else if (model.AvailableAPIs.ContainsKey(fnName))
writer.WriteLine(line);
}
writer.Close();
// Write API function pointers to il2cpp-function-ptr.h // Write API function pointers to il2cpp-function-ptr.h
var il2cppFnPtrFile = Path.Combine(outputPath, "il2cpp-function-ptr.h"); var il2cppFnPtrFile = Path.Combine(outputPath, "il2cpp-function-ptr.h");
@@ -59,7 +81,9 @@ namespace Il2CppInspector.Outputs
writeHeader(); writeHeader();
writeSectionHeader("IL2CPP API function pointers"); writeSectionHeader("IL2CPP API function pointers");
// TODO: Use model.APIExports instead once it is implemented // We could use model.AvailableAPIs here but that would exclude outputting the address
// of API exports which for some reason aren't defined in our selected API header,
// so although it doesn't affect the C++ compilation, we use GetAPIExports() instead for completeness
var exports = model.Package.Binary.GetAPIExports(); var exports = model.Package.Binary.GetAPIExports();
foreach (var export in exports) { foreach (var export in exports) {