public UnityResource(string name) { Name = name; VersionRange = UnityVersionRange.FromFilename(name); }
// Guess which header file(s) correspond to the given metadata+binary. // Note that this may match multiple headers due to structural changes between versions // that are not reflected in the metadata version. public static List <UnityHeaders> GuessHeadersForBinary(Il2CppBinary binary) { List <UnityResource> typeHeaders = new List <UnityResource>(); foreach (var r in GetAllTypeHeaders()) { var metadataVersion = GetMetadataVersionFromFilename(r.Name); if (metadataVersion != binary.Image.Version) { continue; } if (metadataVersion == 21) { /* Special version logic for metadata version 21 based on the Il2CppMetadataRegistration.fieldOffsets field */ var headerFieldOffsetsArePointers = r.VersionRange.Min.CompareTo("5.3.7") >= 0 && r.VersionRange.Min.CompareTo("5.4.0") != 0; var binaryFieldOffsetsArePointers = binary.FieldOffsets == null; if (headerFieldOffsetsArePointers != binaryFieldOffsetsArePointers) { continue; } } typeHeaders.Add(r); } // Get total range of selected headers // Sort is needed because 5.x.x comes before 20xx.x.x in the resource list typeHeaders = typeHeaders.OrderBy(x => x.VersionRange).ToList(); var totalRange = new UnityVersionRange(typeHeaders.First().VersionRange.Min, typeHeaders.Last().VersionRange.Max); // Get all API versions in this range var apis = GetAllAPIHeaders().Where(a => a.VersionRange.Intersect(totalRange) != null).ToList(); // Get the API exports for the binary var exports = binary.GetAPIExports(); // No il2cpp exports? Just return the earliest version from the header range // The API version may be incorrect but should be a subset of the real API and won't cause C++ compile errors if (!exports.Any()) { Console.WriteLine("No IL2CPP API exports found in binary - IL2CPP APIs will be unavailable in C++ project"); return(typeHeaders.Select(t => new UnityHeaders(t, apis.Last(a => a.VersionRange.Intersect(t.VersionRange) != null))).ToList()); } // Go through all of the possible API versions and see how closely they match the binary // Note: if apis.Count == 1, we can't actually narrow down the version range further, // but we still need to check that the APIs actually exist in the binary var apiMatches = new List <UnityResource>(); foreach (var api in apis) { var apiFunctionList = GetFunctionNamesFromAPIHeaderText(api.GetText()); // Every single function in the API list must be an export for a match if (!apiFunctionList.Except(exports.Keys).Any()) { apiMatches.Add(api); } } if (apiMatches.Any()) { // Intersect all API ranges with all header ranges to produce final list of possible ranges Console.WriteLine("IL2CPP API discovery was successful"); return(typeHeaders.SelectMany( t => apiMatches.Where(a => t.VersionRange.Intersect(a.VersionRange) != null) .Select(a => new UnityHeaders(t, a))).ToList()); } // None of the possible API versions match the binary // Select the oldest API version from the group - C++ project compilation will fail Console.WriteLine("No exact match for IL2CPP APIs found in binary - IL2CPP API availability in C++ project will be partial"); return(typeHeaders.Select(t => new UnityHeaders(t, apis.Last(a => a.VersionRange.Intersect(t.VersionRange) != null))).ToList()); }