예제 #1
0
        /// <summary>
        ///     Constructs the map from assembly string to its filename.
        ///
        ///     Roslyn doesn't record the relationship between a filename and its assembly
        ///     information, so we need to retrieve this information manually.
        /// </summary>
        private void SetReferencePaths()
        {
            foreach (var reference in compilation.References.OfType <PortableExecutableReference>())
            {
                try
                {
                    var refPath = reference.FilePath;

                    /*  This method is significantly faster and more lightweight than using
                     *  System.Reflection.Assembly.ReflectionOnlyLoadFrom. It is also allows
                     *  loading the same assembly from different locations.
                     */
                    using var pereader = new System.Reflection.PortableExecutable.PEReader(new FileStream(refPath, FileMode.Open, FileAccess.Read, FileShare.Read));

                    var    metadata = pereader.GetMetadata();
                    string assemblyIdentity;
                    unsafe
                    {
                        var reader = new System.Reflection.Metadata.MetadataReader(metadata.Pointer, metadata.Length);
                        var def    = reader.GetAssemblyDefinition();
                        assemblyIdentity = reader.GetString(def.Name) + " " + def.Version;
                    }
                    extractor.SetAssemblyFile(assemblyIdentity, refPath);
                }
                catch (Exception ex)  // lgtm[cs/catch-of-all-exceptions]
                {
                    extractor.Message(new Message("Exception reading reference file", reference.FilePath, null, ex.StackTrace));
                }
            }
        }
예제 #2
0
            public SharedTestState()
            {
                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    // COM activation is only supported on Windows
                    return;
                }

                ComLibraryFixture = new TestProjectFixture("ComLibrary", RepoDirectories)
                                    .EnsureRestored(RepoDirectories.CorehostPackages)
                                    .BuildProject();

                // Create a .clsidmap from the assembly
                string clsidMapPath = Path.Combine(BaseDirectory, $"{ ComLibraryFixture.TestProject.AssemblyName }.clsidmap");

                using (var assemblyStream = new FileStream(ComLibraryFixture.TestProject.AppDll, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
                    using (var peReader = new System.Reflection.PortableExecutable.PEReader(assemblyStream))
                    {
                        if (peReader.HasMetadata)
                        {
                            MetadataReader reader = peReader.GetMetadataReader();
                            ClsidMap.Create(reader, clsidMapPath);
                        }
                    }

                // Use the locally built comhost to create a comhost with the embedded .clsidmap
                ComHostPath = Path.Combine(
                    ComLibraryFixture.TestProject.BuiltApp.Location,
                    $"{ ComLibraryFixture.TestProject.AssemblyName }.comhost.dll");
                ComHost.Create(
                    Path.Combine(RepoDirectories.CorehostPackages, "comhost.dll"),
                    ComHostPath,
                    clsidMapPath);
            }
예제 #3
0
        public static string GetVersion(string libFolderPath, string libAssembly)
        {
            switch (GetVersionType(libFolderPath, libAssembly))
            {
            case VersionType.Unknown:
                return("");

            case VersionType.V1:
            case VersionType.V2:
            {
                using var fs       = File.OpenRead(Path.Combine(libFolderPath, libAssembly));
                using var peReader = new System.Reflection.PortableExecutable.PEReader(fs);
                var mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None);
                var versionVirtualFileAttribute = GetVirtualFileAttribute(mdReader);
                var attributeReader             = mdReader.GetBlobReader(versionVirtualFileAttribute.Value);
                attributeReader.ReadByte();
                attributeReader.ReadByte();
                attributeReader.ReadSerializedString();
                var xml = attributeReader.ReadSerializedString();
                using var xmlReader = new XmlTextReader(new StringReader(xml));
                xmlReader.Read();
                xmlReader.MoveToAttribute("Value");
                return(xmlReader.Value);
            }

            case VersionType.V3:
            {
                using var fs       = File.OpenRead(Path.Combine(libFolderPath, libAssembly));
                using var peReader = new System.Reflection.PortableExecutable.PEReader(fs);
                var mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None);
                var versionVirtualFileAttribute = GetVirtualFileAttribute(mdReader);
                var attributeReader             = mdReader.GetBlobReader(versionVirtualFileAttribute.Value);
                attributeReader.ReadByte();
                attributeReader.ReadByte();
                attributeReader.ReadSerializedString();
                var xml = attributeReader.ReadSerializedString();
                using var xmlReader = new XmlTextReader(new StringReader(xml));
                xmlReader.Read();
                xmlReader.ReadToDescendant("Singleplayer");
                xmlReader.MoveToAttribute("Value");
                return(xmlReader.Value);
            }

            case VersionType.V4:
            {
                using var fs     = File.OpenRead(Path.Combine(libFolderPath, "Version.xml"));
                using var reader = new StreamReader(fs);
                var xml = reader.ReadToEnd();
                using var xmlReader = new XmlTextReader(new StringReader(xml));
                xmlReader.Read();
                xmlReader.ReadToDescendant("Singleplayer");
                xmlReader.MoveToAttribute("Value");
                var split = xmlReader.Value.Split('.', StringSplitOptions.RemoveEmptyEntries);
                return(string.Join('.', split.Take(split.Length - 1)));
            }

            default:
                return("");
            }
        }
예제 #4
0
        /// <summary>
        /// Reads the assembly info from a file.
        /// This uses System.Reflection.Metadata, which is a very performant and low-level
        /// library. This is very convenient when scanning hundreds of DLLs at a time.
        /// </summary>
        /// <param name="filename">The full filename of the assembly.</param>
        /// <returns>The information about the assembly.</returns>
        public static AssemblyInfo ReadFromFile(string filename)
        {
            var result = new AssemblyInfo()
            {
                Filename = filename
            };

            try
            {
                /*  This method is significantly faster and more lightweight than using
                 *  System.Reflection.Assembly.ReflectionOnlyLoadFrom. It also allows
                 *  loading the same assembly from different locations.
                 */
                using (var pereader = new System.Reflection.PortableExecutable.PEReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                    using (var sha1 = new SHA1CryptoServiceProvider())
                    {
                        var metadata = pereader.GetMetadata();
                        unsafe
                        {
                            var reader = new System.Reflection.Metadata.MetadataReader(metadata.Pointer, metadata.Length);
                            var def    = reader.GetAssemblyDefinition();

                            // This is how you compute the public key token from the full public key.
                            // The last 8 bytes of the SHA1 of the public key.
                            var publicKey       = reader.GetBlobBytes(def.PublicKey);
                            var publicKeyToken  = sha1.ComputeHash(publicKey);
                            var publicKeyString = new StringBuilder();
                            foreach (var b in publicKeyToken.Skip(12).Reverse())
                            {
                                publicKeyString.AppendFormat("{0:x2}", b);
                            }

                            result.Name           = reader.GetString(def.Name);
                            result.Version        = def.Version;
                            result.Culture        = def.Culture.IsNil ? "neutral" : reader.GetString(def.Culture);
                            result.PublicKeyToken = publicKeyString.ToString();
                            result.Valid          = true;
                        }
                    }
            }
            catch (BadImageFormatException)
            {
                // The DLL wasn't an assembly -> result.Valid = false.
            }
            catch (InvalidOperationException)
            {
                // Some other failure -> result.Valid = false.
            }

            return(result);
        }
예제 #5
0
            public SharedTestState()
            {
                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    // COM activation is only supported on Windows
                    return;
                }

                using (var assemblyStream = new FileStream(ComLibraryFixture.TestProject.AppDll, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
                    using (var peReader = new System.Reflection.PortableExecutable.PEReader(assemblyStream))
                    {
                        if (peReader.HasMetadata)
                        {
                            string regFreeManifestPath = Path.Combine(BaseDirectory, $"{ ComLibraryFixture.TestProject.AssemblyName }.X.manifest");

                            MetadataReader reader = peReader.GetMetadataReader();
                            RegFreeComManifest.CreateManifestFromClsidmap(
                                ComLibraryFixture.TestProject.AssemblyName,
                                Path.GetFileName(ComHostPath),
                                reader.GetAssemblyDefinition().Version.ToString(),
                                ClsidMapPath,
                                regFreeManifestPath,
                                TypeLibraries
                                );
                        }
                    }

                string testDirectoryPath = Path.GetDirectoryName(NativeHostPath);
                string comsxsName        = RuntimeInformationExtensions.GetExeFileNameForCurrentPlatform("comsxs");

                ComSxsPath = Path.Combine(testDirectoryPath, comsxsName);
                File.Copy(
                    Path.Combine(RepoDirectories.Artifacts, "corehost_test", comsxsName),
                    ComSxsPath);
                File.Copy(
                    ComHostPath,
                    Path.Combine(testDirectoryPath, Path.GetFileName(ComHostPath)));
                File.Copy(
                    ComLibraryFixture.TestProject.AppDll,
                    Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.AppDll)));
                File.Copy(
                    ComLibraryFixture.TestProject.DepsJson,
                    Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.DepsJson)));
                File.Copy(
                    ComLibraryFixture.TestProject.RuntimeConfigJson,
                    Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.RuntimeConfigJson)));
            }
예제 #6
0
 public static LoadedAssembly FromFile(string path)
 {
     using (var s = File.OpenRead(path))
         using (var pe = new System.Reflection.PortableExecutable.PEReader(s))
         {
             if (!pe.HasMetadata)
             {
                 return(null);
             }
             var holder = new MetadataBlockHolder(pe.GetMetadata());
             if (!holder.Reader.IsAssembly)
             {
                 holder.Dispose();
                 return(null);
             }
             return(new LoadedAssembly(holder));
         }
 }
예제 #7
0
            public SharedTestState()
            {
                if (!OperatingSystem.IsWindows())
                {
                    // COM activation is only supported on Windows
                    return;
                }

                ComLibraryFixture = new TestProjectFixture("ComLibrary", RepoDirectories)
                                    .EnsureRestored()
                                    .BuildProject();

                // Create a .clsidmap from the assembly
                ClsidMapPath = Path.Combine(BaseDirectory, $"{ ComLibraryFixture.TestProject.AssemblyName }.clsidmap");
                using (var assemblyStream = new FileStream(ComLibraryFixture.TestProject.AppDll, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
                    using (var peReader = new System.Reflection.PortableExecutable.PEReader(assemblyStream))
                    {
                        if (peReader.HasMetadata)
                        {
                            MetadataReader reader = peReader.GetMetadataReader();
                            ClsidMap.Create(reader, ClsidMapPath);
                        }
                    }

                // Use the locally built comhost to create a comhost with the embedded .clsidmap
                ComHostPath = Path.Combine(
                    ComLibraryFixture.TestProject.BuiltApp.Location,
                    $"{ ComLibraryFixture.TestProject.AssemblyName }.comhost.dll");

                // Include the test type libraries in the ComHost tests.
                TypeLibraries = new Dictionary <int, string>
                {
                    { 1, Path.Combine(RepoDirectories.Artifacts, "corehost_test", "Server.tlb") },
                    { 2, Path.Combine(RepoDirectories.Artifacts, "corehost_test", "Nested.tlb") }
                };

                ComHost.Create(
                    Path.Combine(RepoDirectories.HostArtifacts, "comhost.dll"),
                    ComHostPath,
                    ClsidMapPath,
                    TypeLibraries);
            }
예제 #8
0
        public static int GetChangeSet(string libFolderPath, string libAssembly)
        {
            switch (GetVersionType(libFolderPath, libAssembly))
            {
            case VersionType.Unknown:
                return(0);

            case VersionType.V1:
                return(0);

            case VersionType.V2:
            case VersionType.V3:
            {
                using var fs       = File.OpenRead(Path.Combine(libFolderPath, libAssembly));
                using var peReader = new System.Reflection.PortableExecutable.PEReader(fs);
                var mdReader        = peReader.GetMetadataReader(MetadataReaderOptions.None);
                var changeSetHandle = mdReader.TypeDefinitions
                                      .GetType(mdReader, "TaleWorlds.Library", "ApplicationVersion")
                                      .GetField(mdReader, "DefaultChangeSet")
                                      .GetDefaultValue();
                var changeSetBlob = mdReader.GetConstant(changeSetHandle).Value;

                return(mdReader.GetBlobReader(changeSetBlob).ReadInt32());
            }

            case VersionType.V4:
            {
                using var fs     = File.OpenRead(Path.Combine(libFolderPath, "Version.xml"));
                using var reader = new StreamReader(fs);
                var xml = reader.ReadToEnd();
                using var xmlReader = new XmlTextReader(new StringReader(xml));
                xmlReader.Read();
                xmlReader.ReadToDescendant("Singleplayer");
                xmlReader.MoveToAttribute("Value");
                var split = xmlReader.Value.Split('.', StringSplitOptions.RemoveEmptyEntries);
                return(int.Parse(split.Last()));
            }

            default:
                return(0);
            }
        }
예제 #9
0
        static int ValidateMIbcData(TypeSystemContext tsc, FileInfo outputFileName, byte[] moduleBytes, IEnumerable <MethodProfileData> methodsToAttemptToPrepare)
        {
            var peReader    = new System.Reflection.PortableExecutable.PEReader(System.Collections.Immutable.ImmutableArray.Create <byte>(moduleBytes));
            var profileData = MIbcProfileParser.ParseMIbcFile(tsc, peReader, null, null);
            Dictionary <MethodDesc, MethodProfileData> mibcDict = new Dictionary <MethodDesc, MethodProfileData>();

            foreach (var mibcData in profileData.GetAllMethodProfileData())
            {
                mibcDict.Add((MethodDesc)(object)mibcData.Method, mibcData);
            }

            bool failure = false;

            if (methodsToAttemptToPrepare.Count() != mibcDict.Count)
            {
                Program.PrintError($"Not same count of methods {methodsToAttemptToPrepare.Count()} != {mibcDict.Count}");
                failure = true;
            }

            foreach (var entry in methodsToAttemptToPrepare)
            {
                MethodDesc method = entry.Method;
                if (!mibcDict.ContainsKey(method))
                {
                    Program.PrintError($"{method} not found in mibcEntryData");
                    failure = true;
                    continue;
                }
            }

            if (failure)
            {
                return(-1);
            }
            else
            {
                Program.PrintMessage($"Validated {outputFileName.FullName}");
                return(0);
            }
        }
예제 #10
0
        private static Version GetAssemblyVersion(string path)
        {
            if (!string.IsNullOrEmpty(path) && File.Exists(path))
            {
                using (var fileStream = File.OpenRead(path))
                {
                    using (var peReader = new System.Reflection.PortableExecutable.PEReader(fileStream))
                    {
                        var mdMemoryBlock = peReader.GetMetadata();
                        unsafe
                        {
                            var metadataReader = new System.Reflection.Metadata.MetadataReader(
                                mdMemoryBlock.Pointer,
                                mdMemoryBlock.Length);

                            var asmDef = metadataReader.GetAssemblyDefinition();
                            return(asmDef.Version);
                        }
                    }
                }
            }
            return(null);
        }
예제 #11
0
        static IEnumerable <MIbcData> ReadMIbcData(TraceTypeSystemContext tsc, FileInfo outputFileName, byte[] moduleBytes)
        {
            var peReader = new System.Reflection.PortableExecutable.PEReader(System.Collections.Immutable.ImmutableArray.Create <byte>(moduleBytes));
            var module   = EcmaModule.Create(tsc, peReader, null, null, new CustomCanonResolver(tsc));

            var          loadedMethod = (EcmaMethod)module.GetGlobalModuleType().GetMethod("AssemblyDictionary", null);
            EcmaMethodIL ilBody       = EcmaMethodIL.Create(loadedMethod);

            byte[] ilBytes       = ilBody.GetILBytes();
            int    currentOffset = 0;

            while (currentOffset < ilBytes.Length)
            {
                ILOpcode opcode = (ILOpcode)ilBytes[currentOffset];
                if (opcode == ILOpcode.prefix1)
                {
                    opcode = 0x100 + (ILOpcode)ilBytes[currentOffset + 1];
                }
                switch (opcode)
                {
                case ILOpcode.ldtoken:
                    UInt32 token = (UInt32)(ilBytes[currentOffset + 1] + (ilBytes[currentOffset + 2] << 8) + (ilBytes[currentOffset + 3] << 16) + (ilBytes[currentOffset + 4] << 24));
                    foreach (var data in ReadMIbcGroup(tsc, (EcmaMethod)ilBody.GetObject((int)token)))
                    {
                        yield return(data);
                    }
                    break;

                case ILOpcode.pop:
                    break;
                }

                // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                currentOffset += opcode.GetSize();
            }
            GC.KeepAlive(peReader);
        }
예제 #12
0
        public MethodMemoryMap(
            TraceProcess p,
            TraceTypeSystemContext tsc,
            TraceRuntimeDescToTypeSystemDesc idParser,
            int clrInstanceID)
        {
            // Capture the addresses of jitted code
            List <MemoryRegionInfo>             infos = new List <MemoryRegionInfo>();
            Dictionary <long, MemoryRegionInfo> info  = new Dictionary <long, MemoryRegionInfo>();

            foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadTraceData>())
            {
                if (e.ClrInstanceID != clrInstanceID)
                {
                    continue;
                }

                MethodDesc method = null;
                try
                {
                    method = idParser.ResolveMethodID(e.MethodID);
                }
                catch
                {
                }

                if (method != null)
                {
                    infos.Add(new MemoryRegionInfo
                    {
                        StartAddress = e.MethodStartAddress,
                        EndAddress   = e.MethodStartAddress + checked ((uint)e.MethodSize),
                        MethodID     = e.MethodID,
                        Method       = method,
                    });
                }
            }

            foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadVerboseTraceData>())
            {
                if (e.ClrInstanceID != clrInstanceID)
                {
                    continue;
                }

                MethodDesc method = null;
                try
                {
                    method = idParser.ResolveMethodID(e.MethodID);
                }
                catch
                {
                }

                if (method != null)
                {
                    infos.Add(new MemoryRegionInfo
                    {
                        StartAddress = e.MethodStartAddress,
                        EndAddress   = e.MethodStartAddress + checked ((uint)e.MethodSize),
                        MethodID     = e.MethodID,
                        Method       = method,
                    });
                }
            }

            var sigProvider = new R2RSignatureTypeProvider(tsc);

            foreach (var module in p.LoadedModules)
            {
                if (module.FilePath == "")
                {
                    continue;
                }

                if (!File.Exists(module.FilePath))
                {
                    continue;
                }

                try
                {
                    byte[] image = File.ReadAllBytes(module.FilePath);
                    using (FileStream fstream = new FileStream(module.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        var r2rCheckPEReader = new System.Reflection.PortableExecutable.PEReader(fstream, System.Reflection.PortableExecutable.PEStreamOptions.LeaveOpen);

                        if (!ILCompiler.Reflection.ReadyToRun.ReadyToRunReader.IsReadyToRunImage(r2rCheckPEReader))
                        {
                            continue;
                        }
                    }

                    var reader = new ILCompiler.Reflection.ReadyToRun.ReadyToRunReader(tsc, module.FilePath);
                    foreach (var methodEntry in reader.GetCustomMethodToRuntimeFunctionMapping <TypeDesc, MethodDesc, R2RSigProviderContext>(sigProvider))
                    {
                        foreach (var runtimeFunction in methodEntry.Value.RuntimeFunctions)
                        {
                            infos.Add(new MemoryRegionInfo
                            {
                                StartAddress  = module.ImageBase + (ulong)runtimeFunction.StartAddress,
                                EndAddress    = module.ImageBase + (ulong)runtimeFunction.StartAddress + (uint)runtimeFunction.Size,
                                Method        = methodEntry.Key,
                                NativeToILMap = runtimeFunction.DebugInfo != null ? NativeToILMap.FromR2RBounds(runtimeFunction.DebugInfo.BoundsList) : null,
                            });
                        }
                    }
                }
                catch { }
            }

            // Can have duplicate events, so pick first for each
            var byMethodID = infos.GroupBy(i => i.MethodID).ToDictionary(g => g.Key, g => g.First());

            foreach (MethodILToNativeMapTraceData e in p.EventsInProcess.ByEventType <MethodILToNativeMapTraceData>())
            {
                if (byMethodID.TryGetValue(e.MethodID, out MemoryRegionInfo inf))
                {
                    inf.NativeToILMap = NativeToILMap.FromEvent(e);
                }
            }

            _infos    = byMethodID.Values.OrderBy(i => i.StartAddress).ToArray();
            _infoKeys = _infos.Select(i => i.StartAddress).ToArray();

#if DEBUG
            for (int i = 0; i < _infos.Length - 1; i++)
            {
                var cur  = _infos[i];
                var next = _infos[i + 1];
                if (cur.EndAddress <= next.StartAddress)
                {
                    continue;
                }

                Debug.Fail("Overlap in memory ranges");
            }
#endif
        }
예제 #13
0
        /// <summary>
        /// Parse an MIBC file for the methods that are interesting.
        /// The version bubble must be specified and will describe the restrict the set of methods parsed to those relevant to the compilation
        /// The onlyDefinedInAssembly parameter is used to restrict the set of types parsed to include only those which are defined in a specific module. Specify null to allow definitions from all modules.
        /// This limited parsing is not necessarily an exact set of prevention, so detailed algorithms that work at the individual method level are still necessary, but this allows avoiding excessive parsing.
        ///
        /// The format of the Mibc file is that of a .NET dll, with a global method named "AssemblyDictionary". Inside of that file are a series of references that are broken up by which assemblies define the individual methods.
        /// These references are encoded as IL code that represents the details.
        /// The format of these IL instruction is as follows.
        ///
        /// ldstr mibcGroupName
        /// ldtoken mibcGroupMethod
        /// pop
        /// {Repeat the above pattern N times, once per Mibc group}
        ///
        /// See comment above ReadMIbcGroup for details of the group format
        ///
        /// The mibcGroupName is in the following format "Assembly_{definingAssemblyName};{OtherAssemblyName};{OtherAssemblyName};...; (OtherAssemblyName is ; delimited)
        ///
        /// </summary>
        /// <returns></returns>
        public static ProfileData ParseMIbcFile(CompilerTypeSystemContext tsc, string filename, HashSet <string> assemblyNamesInVersionBubble, string onlyDefinedInAssembly)
        {
            byte[] peData;

            using (var zipFile = ZipFile.OpenRead(filename))
            {
                var mibcDataEntry = zipFile.GetEntry(Path.GetFileName(filename) + ".dll");
                using (var mibcDataStream = mibcDataEntry.Open())
                {
                    peData = new byte[mibcDataEntry.Length];
                    using (BinaryReader br = new BinaryReader(mibcDataStream))
                    {
                        peData = br.ReadBytes(checked ((int)mibcDataEntry.Length));
                    }
                }
            }

            using (var peReader = new System.Reflection.PortableExecutable.PEReader(System.Collections.Immutable.ImmutableArray.Create <byte>(peData)))
            {
                var mibcModule = EcmaModule.Create(tsc, peReader, null, null, new CustomCanonResolver(tsc));

                var assemblyDictionary = (EcmaMethod)mibcModule.GetGlobalModuleType().GetMethod("AssemblyDictionary", null);
                IEnumerable <MethodProfileData> loadedMethodProfileData = Enumerable.Empty <MethodProfileData>();

                EcmaMethodIL ilBody        = EcmaMethodIL.Create(assemblyDictionary);
                byte[]       ilBytes       = ilBody.GetILBytes();
                int          currentOffset = 0;

                string mibcGroupName = "";
                while (currentOffset < ilBytes.Length)
                {
                    ILOpcode opcode = (ILOpcode)ilBytes[currentOffset];
                    if (opcode == ILOpcode.prefix1)
                    {
                        opcode = 0x100 + (ILOpcode)ilBytes[currentOffset + 1];
                    }
                    switch (opcode)
                    {
                    case ILOpcode.ldstr:
                        if (mibcGroupName == "")
                        {
                            UInt32 userStringToken = (UInt32)(ilBytes[currentOffset + 1] + (ilBytes[currentOffset + 2] << 8) + (ilBytes[currentOffset + 3] << 16) + (ilBytes[currentOffset + 4] << 24));
                            mibcGroupName = (string)ilBody.GetObject((int)userStringToken);
                        }
                        break;

                    case ILOpcode.ldtoken:
                        if (String.IsNullOrEmpty(mibcGroupName))
                        {
                            break;
                        }

                        string[] assembliesByName = mibcGroupName.Split(';');

                        bool hasMatchingDefinition = (onlyDefinedInAssembly == null) || assembliesByName[0].Equals(onlyDefinedInAssembly);

                        if (!hasMatchingDefinition)
                        {
                            break;
                        }

                        bool areAllEntriesInVersionBubble = true;
                        foreach (string s in assembliesByName)
                        {
                            if (string.IsNullOrEmpty(s))
                            {
                                continue;
                            }

                            if (!assemblyNamesInVersionBubble.Contains(s))
                            {
                                areAllEntriesInVersionBubble = false;
                                break;
                            }
                        }

                        if (!areAllEntriesInVersionBubble)
                        {
                            break;
                        }

                        uint token = (uint)(ilBytes[currentOffset + 1] + (ilBytes[currentOffset + 2] << 8) + (ilBytes[currentOffset + 3] << 16) + (ilBytes[currentOffset + 4] << 24));
                        loadedMethodProfileData = loadedMethodProfileData.Concat(ReadMIbcGroup(tsc, (EcmaMethod)ilBody.GetObject((int)token)));
                        break;

                    case ILOpcode.pop:
                        mibcGroupName = "";
                        break;
                    }

                    // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                    currentOffset += opcode.GetSize();
                }

                return(new IBCProfileData(false, loadedMethodProfileData));
            }
        }
예제 #14
0
            public SharedTestState()
            {
                if (!OperatingSystem.IsWindows())
                {
                    // COM activation is only supported on Windows
                    return;
                }

                string comsxsDirectory     = BaseDirectory;
                string regFreeManifestName = $"{ ComLibraryFixture.TestProject.AssemblyName }.X.manifest";
                string regFreeManifestPath = Path.Combine(comsxsDirectory, regFreeManifestName);

                using (var assemblyStream = new FileStream(ComLibraryFixture.TestProject.AppDll, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
                    using (var peReader = new System.Reflection.PortableExecutable.PEReader(assemblyStream))
                    {
                        if (peReader.HasMetadata)
                        {
                            MetadataReader reader = peReader.GetMetadataReader();
                            RegFreeComManifest.CreateManifestFromClsidmap(
                                ComLibraryFixture.TestProject.AssemblyName,
                                Path.GetFileName(ComHostPath),
                                reader.GetAssemblyDefinition().Version.ToString(),
                                ClsidMapPath,
                                regFreeManifestPath,
                                TypeLibraries
                                );
                        }
                    }

                string comsxsName = RuntimeInformationExtensions.GetExeFileNameForCurrentPlatform("comsxs");

                ComSxsPath = Path.Combine(comsxsDirectory, comsxsName);
                File.Copy(
                    Path.Combine(RepoDirectories.Artifacts, "corehost_test", comsxsName),
                    ComSxsPath);

                ManagedHostFixture_FrameworkDependent = new TestProjectFixture("ManagedHost", RepoDirectories)
                                                        .EnsureRestored()
                                                        .PublishProject(selfContained: false, extraArgs: "/p:RegFreeCom=true");
                File.Copy(regFreeManifestPath, Path.Combine(ManagedHostFixture_FrameworkDependent.TestProject.BuiltApp.Location, regFreeManifestName));

                ManagedHostFixture_SelfContained = new TestProjectFixture("ManagedHost", RepoDirectories)
                                                   .EnsureRestored()
                                                   .PublishProject(selfContained: true, extraArgs: "/p:RegFreeCom=true");
                File.Copy(regFreeManifestPath, Path.Combine(ManagedHostFixture_SelfContained.TestProject.BuiltApp.Location, regFreeManifestName));

                // Copy the ComLibrary output and comhost to the ComSxS and ManagedHost directories
                string[] toCopy =
                {
                    ComLibraryFixture.TestProject.AppDll,
                    ComLibraryFixture.TestProject.DepsJson,
                    ComLibraryFixture.TestProject.RuntimeConfigJson,
                    ComHostPath,
                };
                foreach (string filePath in toCopy)
                {
                    File.Copy(filePath, Path.Combine(comsxsDirectory, Path.GetFileName(filePath)));
                    File.Copy(filePath, Path.Combine(ManagedHostFixture_FrameworkDependent.TestProject.BuiltApp.Location, Path.GetFileName(filePath)));
                    File.Copy(filePath, Path.Combine(ManagedHostFixture_SelfContained.TestProject.BuiltApp.Location, Path.GetFileName(filePath)));
                }
            }
예제 #15
0
        public MethodMemoryMap(
            TraceProcess p,
            TraceTypeSystemContext tsc,
            TraceRuntimeDescToTypeSystemDesc idParser,
            int clrInstanceID,
            FileInfo preciseDebugInfoFile,
            Logger logger)
        {
            // Capture the addresses of jitted code
            List <MemoryRegionInfo> infos = new List <MemoryRegionInfo>();
            Dictionary <JittedID, MemoryRegionInfo> info = new Dictionary <JittedID, MemoryRegionInfo>();

            foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadTraceData>())
            {
                if (e.ClrInstanceID != clrInstanceID)
                {
                    continue;
                }

                MethodDesc method = null;
                try
                {
                    method = idParser.ResolveMethodID(e.MethodID);
                }
                catch
                {
                }

                if (method != null)
                {
                    JittedID jittedID = new JittedID(e.MethodID, 0);
                    if (!info.ContainsKey(jittedID))
                    {
                        info.Add(jittedID, new MemoryRegionInfo
                        {
                            StartAddress = e.MethodStartAddress,
                            EndAddress   = e.MethodStartAddress + checked ((uint)e.MethodSize),
                            Method       = method,
                        });
                    }
                }
            }

            foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadVerboseTraceData>())
            {
                if (e.ClrInstanceID != clrInstanceID)
                {
                    continue;
                }

                MethodDesc method = null;
                try
                {
                    method = idParser.ResolveMethodID(e.MethodID, throwIfNotFound: false);
                }
                catch
                {
                }

                if (method != null)
                {
                    JittedID jittedID = new JittedID(e.MethodID, e.ReJITID);
                    if (!info.ContainsKey(jittedID))
                    {
                        info.Add(jittedID, new MemoryRegionInfo
                        {
                            StartAddress = e.MethodStartAddress,
                            EndAddress   = e.MethodStartAddress + checked ((uint)e.MethodSize),
                            Method       = method,
                        });
                    }
                }
            }

            var sigProvider = new R2RSignatureTypeProviderForGlobalTables(tsc);

            foreach (var module in p.LoadedModules)
            {
                if (module.FilePath == "")
                {
                    continue;
                }

                if (!File.Exists(module.FilePath))
                {
                    continue;
                }

                try
                {
                    byte[] image = File.ReadAllBytes(module.FilePath);
                    using (FileStream fstream = new FileStream(module.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        var r2rCheckPEReader = new System.Reflection.PortableExecutable.PEReader(fstream, System.Reflection.PortableExecutable.PEStreamOptions.LeaveOpen);

                        if (!ILCompiler.Reflection.ReadyToRun.ReadyToRunReader.IsReadyToRunImage(r2rCheckPEReader))
                        {
                            continue;
                        }
                    }

                    var reader = new ILCompiler.Reflection.ReadyToRun.ReadyToRunReader(tsc, module.FilePath);
                    foreach (var methodEntry in reader.GetCustomMethodToRuntimeFunctionMapping <TypeDesc, MethodDesc, R2RSigProviderContext>(sigProvider))
                    {
                        foreach (var runtimeFunction in methodEntry.Value.RuntimeFunctions)
                        {
                            infos.Add(new MemoryRegionInfo
                            {
                                StartAddress  = module.ImageBase + (ulong)runtimeFunction.StartAddress,
                                EndAddress    = module.ImageBase + (ulong)runtimeFunction.StartAddress + (uint)runtimeFunction.Size,
                                Method        = methodEntry.Key,
                                NativeToILMap = runtimeFunction.DebugInfo != null ? CreateNativeToILMap(methodEntry.Key, runtimeFunction.DebugInfo.BoundsList) : null,
                            });
                        }
                    }
                }
                catch
                {
                    logger.PrintWarning($"Failed to load method entry points from R2R module {module.FilePath}");
                }
            }

            List <PreciseDebugInfo> preciseInfos = null;

            if (preciseDebugInfoFile != null)
            {
                preciseInfos =
                    File.ReadAllLines(preciseDebugInfoFile.FullName)
                    .Select(l => JsonSerializer.Deserialize <PreciseDebugInfo>(l))
                    .ToList();
            }

            if (preciseInfos != null && preciseInfos.Count > 0)
            {
                foreach (PreciseDebugInfo preciseDebugInf in preciseInfos)
                {
                    if (info.TryGetValue(new JittedID((long)preciseDebugInf.MethodID, 0), out MemoryRegionInfo inf))
                    {
                        inf.NativeToILMap = CreateNativeToILMap(idParser, preciseDebugInf);
                    }
                }
            }
            else
            {
                // Associate NativeToILMap with MethodLoad event found Memory Regions
                foreach (MethodILToNativeMapTraceData e in p.EventsInProcess.ByEventType <MethodILToNativeMapTraceData>())
                {
                    if (info.TryGetValue(new JittedID(e.MethodID, e.ReJITID), out MemoryRegionInfo inf))
                    {
                        inf.NativeToILMap = CreateNativeToILMap(inf.Method, e);
                    }
                }
            }

            // Sort the R2R data by StartAddress
            MemoryRegionInfoStartAddressComparer startAddressComparer = new MemoryRegionInfoStartAddressComparer();

            infos.Sort(startAddressComparer);

            // For each method found via MethodLoad events, check to see if it exists in the infos array, and if it does not, build a list to add
            List <MemoryRegionInfo> memoryRegionsToAdd = new List <MemoryRegionInfo>();

            foreach (var methodLoadInfo in info.Values)
            {
                int searchResult = infos.BinarySearch(methodLoadInfo, startAddressComparer);
                if (searchResult < 0)
                {
                    memoryRegionsToAdd.Add(methodLoadInfo);
                }
            }

            // Add the regions from the MethodLoad events, and keep the overall array sorted
            infos.AddRange(memoryRegionsToAdd);
            infos.Sort(startAddressComparer);

            _infos = infos.ToArray();

            _infoKeys = _infos.Select(i => i.StartAddress).ToArray();

#if DEBUG
            for (int i = 0; i < _infos.Length - 1; i++)
            {
                var cur  = _infos[i];
                var next = _infos[i + 1];
                if (cur.EndAddress <= next.StartAddress)
                {
                    continue;
                }

                Debug.Fail("Overlap in memory ranges");
            }
#endif
        }
예제 #16
0
        public static VersionType GetVersionType(string libFolderPath, string libAssembly)
        {
            if (File.Exists(Path.Combine(libFolderPath, "Version.xml")))
            {
                return(VersionType.V4);
            }

            using var fs       = File.OpenRead(Path.Combine(libFolderPath, libAssembly));
            using var peReader = new System.Reflection.PortableExecutable.PEReader(fs);
            var mdReader = peReader.GetMetadataReader(MetadataReaderOptions.None);


            var applicationVersionDef = mdReader.TypeDefinitions
                                        .GetType(mdReader, "TaleWorlds.Library", "ApplicationVersion");
            var hasChangeSet = applicationVersionDef.GetFields()
                               .Any(f => mdReader.GetString(mdReader.GetFieldDefinition(f).Name) == "DefaultChangeSet");


            var versionVirtualFileAttribute = GetVirtualFileAttribute(mdReader);

            var attributeReader = mdReader.GetBlobReader(versionVirtualFileAttribute.Value);

            if (attributeReader.ReadByte() != 0x01 || attributeReader.ReadByte() != 0x00)
            {
                throw new NotImplementedException("Custom Attribute prolog is invalid.");
            }

            var fn = attributeReader.ReadSerializedString();

            if (fn != "Version.xml")
            {
                throw new NotImplementedException("Version field doesn't have Version.xml attribute.");
            }

            var xml = attributeReader.ReadSerializedString();

            using var xmlReader = new XmlTextReader(new StringReader(xml));

            if (!xmlReader.Read())
            {
                throw new NotImplementedException("Can't parse XML content of Version.xml");
            }

            if (hasChangeSet)
            {
                if (!xmlReader.MoveToAttribute("Value"))
                {
                    if (!xmlReader.ReadToDescendant("Singleplayer"))
                    {
                        return(VersionType.Unknown);
                    }
                    return(VersionType.V3);
                }
                return(VersionType.V2);
            }
            else
            {
                if (!xmlReader.MoveToAttribute("Value"))
                {
                    return(VersionType.Unknown);
                }
                return(VersionType.V1);
            }
        }