Exemplo n.º 1
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
        }
Exemplo n.º 2
0
        public MethodMemoryMap(
            TraceProcess p,
            TraceTypeSystemContext tsc,
            TraceRuntimeDescToTypeSystemDesc idParser,
            int clrInstanceID,
            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 ? NativeToILMap.FromR2RBounds(runtimeFunction.DebugInfo.BoundsList) : null,
                            });
                        }
                    }
                }
                catch
                {
                    logger.PrintWarning($"Failed to load method entry points from R2R module {module.FilePath}");
                }
            }

            // 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 = NativeToILMap.FromEvent(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
        }