예제 #1
0
 public UnityResource(string name)
 {
     Name         = name;
     VersionRange = UnityVersionRange.FromFilename(name);
 }
예제 #2
0
        // 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());
        }