Exemplo n.º 1
0
        /// <summary>
        /// Read the EH clause from a given file offset in the PE image.
        /// </summary>
        /// <param name="reader">R2R image reader<param>
        /// <param name="offset">Offset of the EH clause in the image</param>
        public EHClause(ReadyToRunReader reader, int offset)
        {
            Flags                    = (CorExceptionFlag)BitConverter.ToUInt32(reader.Image, offset + 0 * sizeof(uint));
            TryOffset                = BitConverter.ToUInt32(reader.Image, offset + 1 * sizeof(uint));
            TryEnd                   = BitConverter.ToUInt32(reader.Image, offset + 2 * sizeof(uint));
            HandlerOffset            = BitConverter.ToUInt32(reader.Image, offset + 3 * sizeof(uint));
            HandlerEnd               = BitConverter.ToUInt32(reader.Image, offset + 4 * sizeof(uint));
            ClassTokenOrFilterOffset = BitConverter.ToUInt32(reader.Image, offset + 5 * sizeof(uint));

            if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_KIND_MASK) == CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_NONE)
            {
                ClassName = MetadataNameFormatter.FormatHandle(reader.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
            }
        }
Exemplo n.º 2
0
        public RuntimeFunction(
            ReadyToRunReader readyToRunReader,
            int id,
            int startRva,
            int endRva,
            int unwindRva,
            int codeOffset,
            ReadyToRunMethod method,
            BaseUnwindInfo unwindInfo,
            BaseGcInfo gcInfo,
            EHInfo ehInfo)
        {
            _readyToRunReader = readyToRunReader;
            Id           = id;
            StartAddress = startRva;
            UnwindRVA    = unwindRva;
            Method       = method;
            UnwindInfo   = unwindInfo;

            if (endRva != -1)
            {
                Size = endRva - startRva;
            }
            else if (unwindInfo is x86.UnwindInfo)
            {
                Size = (int)((x86.UnwindInfo)unwindInfo).FunctionLength;
            }
            else if (unwindInfo is Arm.UnwindInfo)
            {
                Size = (int)((Arm.UnwindInfo)unwindInfo).FunctionLength;
            }
            else if (unwindInfo is Arm64.UnwindInfo)
            {
                Size = (int)((Arm64.UnwindInfo)unwindInfo).FunctionLength;
            }
            else if (gcInfo != null)
            {
                Size = gcInfo.CodeLength;
            }
            else
            {
                Size = -1;
            }
            CodeOffset    = codeOffset;
            method.GcInfo = gcInfo;
            EHInfo        = ehInfo;
        }
Exemplo n.º 3
0
        private void EnsureInitialized()
        {
            if (_boundsList != null)
            {
                return;
            }
            ReadyToRunReader _readyToRunReader = _runtimeFunction.ReadyToRunReader;
            int offset = _offset;

            _boundsList    = new List <DebugInfoBoundsEntry>();
            _variablesList = new List <NativeVarInfo>();
            Machine machine = _readyToRunReader.Machine;

            byte[] image = _readyToRunReader.Image;
            _machine = machine;

            // Get the id of the runtime function from the NativeArray
            uint lookback        = 0;
            uint debugInfoOffset = NativeReader.DecodeUnsigned(image, (uint)offset, ref lookback);

            if (lookback != 0)
            {
                System.Diagnostics.Debug.Assert(0 < lookback && lookback < offset);
                debugInfoOffset = (uint)offset - lookback;
            }

            NibbleReader reader             = new NibbleReader(image, (int)debugInfoOffset);
            uint         boundsByteCount    = reader.ReadUInt();
            uint         variablesByteCount = reader.ReadUInt();
            int          boundsOffset       = reader.GetNextByteOffset();
            int          variablesOffset    = (int)(boundsOffset + boundsByteCount);

            if (boundsByteCount > 0)
            {
                ParseBounds(image, boundsOffset);
            }

            if (variablesByteCount > 0)
            {
                ParseNativeVarInfo(image, variablesOffset);
            }
        }
Exemplo n.º 4
0
        public RuntimeFunction(
            ReadyToRunReader readyToRunReader,
            int id,
            int startRva,
            int endRva,
            int unwindRva,
            int codeOffset,
            ReadyToRunMethod method,
            BaseUnwindInfo unwindInfo)
        {
            _readyToRunReader = readyToRunReader;

            Id           = id;
            StartAddress = startRva;
            EndAddress   = endRva;
            UnwindRVA    = unwindRva;
            Method       = method;
            UnwindInfo   = unwindInfo;
            CodeOffset   = codeOffset;
        }
Exemplo n.º 5
0
        public static TransitionBlock FromReader(ReadyToRunReader reader)
        {
            switch (reader.Architecture)
            {
            case Architecture.X86:
                return(X86TransitionBlock.Instance);

            case Architecture.X64:
                return(reader.OperatingSystem == OperatingSystem.Windows ? X64WindowsTransitionBlock.Instance : X64UnixTransitionBlock.Instance);

            case Architecture.Arm:
                return(ArmTransitionBlock.Instance);

            case Architecture.Arm64:
                return(Arm64TransitionBlock.Instance);

            default:
                throw new NotImplementedException();
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Read the EH clause from a given file offset in the PE image.
        /// </summary>
        /// <param name="reader">R2R image reader<param>
        /// <param name="offset">Offset of the EH clause in the image</param>
        public EHClause(ReadyToRunReader reader, int offset)
        {
            Flags                    = (CorExceptionFlag)BitConverter.ToUInt32(reader.Image, offset + 0 * sizeof(uint));
            TryOffset                = BitConverter.ToUInt32(reader.Image, offset + 1 * sizeof(uint));
            TryEnd                   = BitConverter.ToUInt32(reader.Image, offset + 2 * sizeof(uint));
            HandlerOffset            = BitConverter.ToUInt32(reader.Image, offset + 3 * sizeof(uint));
            HandlerEnd               = BitConverter.ToUInt32(reader.Image, offset + 4 * sizeof(uint));
            ClassTokenOrFilterOffset = BitConverter.ToUInt32(reader.Image, offset + 5 * sizeof(uint));

            if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_KIND_MASK) == CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_NONE)
            {
                if (reader.Composite)
                {
                    // TODO: EH clauses in composite mode
                    ClassName = "TODO-composite module in EH clause";
                }
                else
                {
                    ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadata()?.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
                }
            }
        }
Exemplo n.º 7
0
 public PgoDataLoader(ReadyToRunReader r2rReader, SignatureFormattingOptions formatOptions)
 {
     _formatOptions = formatOptions;
     _r2rReader     = r2rReader;
 }
 public InliningInfoSection2(ReadyToRunReader reader, int offset, int endOffset)
 {
     _r2r         = reader;
     _startOffset = offset;
     _endOffset   = endOffset;
 }
Exemplo n.º 9
0
        /// <summary>
        /// Extracts the method signature from the metadata by rid
        /// </summary>
        public ReadyToRunMethod(
            ReadyToRunReader readyToRunReader,
            IAssemblyMetadata componentReader,
            EntityHandle methodHandle,
            int entryPointId,
            string owningType,
            string constrainedType,
            string[] instanceArgs,
            int?fixupOffset)
        {
            _readyToRunReader           = readyToRunReader;
            _fixupOffset                = fixupOffset;
            MethodHandle                = methodHandle;
            EntryPointRuntimeFunctionId = entryPointId;

            ComponentReader = componentReader;

            EntityHandle owningTypeHandle;
            GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection);

            DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs);
            DisassemblingTypeProvider   typeProvider   = new DisassemblingTypeProvider();

            // get the method signature from the method handle
            switch (MethodHandle.Kind)
            {
            case HandleKind.MethodDefinition:
            {
                MethodDefinition methodDef = ComponentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle);
                if (methodDef.RelativeVirtualAddress != 0)
                {
                    MethodBodyBlock mbb = ComponentReader.ImageReader.GetMethodBody(methodDef.RelativeVirtualAddress);
                    if (!mbb.LocalSignature.IsNil)
                    {
                        StandaloneSignature ss = ComponentReader.MetadataReader.GetStandaloneSignature(mbb.LocalSignature);
                        LocalSignature = ss.DecodeLocalSignature(typeProvider, genericContext);
                    }
                }
                Name             = ComponentReader.MetadataReader.GetString(methodDef.Name);
                Signature        = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext);
                owningTypeHandle = methodDef.GetDeclaringType();
                genericParams    = methodDef.GetGenericParameters();
            }
            break;

            case HandleKind.MemberReference:
            {
                MemberReference memberRef = ComponentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle);
                Name             = ComponentReader.MetadataReader.GetString(memberRef.Name);
                Signature        = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext);
                owningTypeHandle = memberRef.Parent;
            }
            break;

            default:
                throw new NotImplementedException();
            }

            if (owningType != null)
            {
                DeclaringType = owningType;
            }
            else
            {
                DeclaringType = MetadataNameFormatter.FormatHandle(ComponentReader.MetadataReader, owningTypeHandle);
            }

            StringBuilder sb = new StringBuilder();

            sb.Append(Signature.ReturnType);
            sb.Append(" ");
            sb.Append(DeclaringType);
            sb.Append(".");
            sb.Append(Name);

            if (Signature.GenericParameterCount != 0)
            {
                sb.Append("<");
                for (int i = 0; i < Signature.GenericParameterCount; i++)
                {
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }
                    if (instanceArgs != null && instanceArgs.Length > i)
                    {
                        sb.Append(instanceArgs[i]);
                    }
                    else
                    {
                        sb.Append("!");
                        sb.Append(i);
                    }
                }
                sb.Append(">");
            }

            sb.Append("(");
            for (int i = 0; i < Signature.ParameterTypes.Length; i++)
            {
                if (i > 0)
                {
                    sb.Append(", ");
                }
                sb.AppendFormat($"{Signature.ParameterTypes[i]}");
            }
            sb.Append(")");

            SignatureString = sb.ToString();
        }
Exemplo n.º 10
0
 public DebugInfo(ReadyToRunReader readyToRunReader, int offset)
 {
     this._readyToRunReader = readyToRunReader;
     this._offset           = offset;
 }
Exemplo n.º 11
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
        }
Exemplo n.º 12
0
 internal ReadyToRunAssembly(ReadyToRunReader reader)
 {
     _reader = reader;
 }
Exemplo n.º 13
0
        static int InnerProcessTraceFileMain(CommandLineOptions commandLineOptions)
        {
            if (commandLineOptions.TraceFile == null)
            {
                PrintUsage(commandLineOptions, "--trace must be specified");
                return(-8);
            }

            if (commandLineOptions.OutputFileName == null)
            {
                PrintUsage(commandLineOptions, "--output must be specified");
                return(-8);
            }

            if (commandLineOptions.OutputFileName != null)
            {
                if (!commandLineOptions.FileType.HasValue)
                {
                    PrintUsage(commandLineOptions, $"--pgo-file-type must be specified");
                    return(-9);
                }
                if ((commandLineOptions.FileType.Value != PgoFileType.jittrace) && (commandLineOptions.FileType != PgoFileType.mibc))
                {
                    PrintUsage(commandLineOptions, $"Invalid output pgo type {commandLineOptions.FileType} specified.");
                    return(-9);
                }
                if (commandLineOptions.FileType == PgoFileType.jittrace)
                {
                    if (!commandLineOptions.OutputFileName.Name.EndsWith(".jittrace"))
                    {
                        PrintUsage(commandLineOptions, $"jittrace output file name must end with .jittrace");
                        return(-9);
                    }
                }
                if (commandLineOptions.FileType == PgoFileType.mibc)
                {
                    if (!commandLineOptions.OutputFileName.Name.EndsWith(".mibc"))
                    {
                        PrintUsage(commandLineOptions, $"mibc output file name must end with .mibc");
                        return(-9);
                    }
                }
            }

            string etlFileName = commandLineOptions.TraceFile.FullName;

            foreach (string nettraceExtension in new string[] { ".netperf", ".netperf.zip", ".nettrace" })
            {
                if (commandLineOptions.TraceFile.FullName.EndsWith(nettraceExtension))
                {
                    etlFileName = commandLineOptions.TraceFile.FullName.Substring(0, commandLineOptions.TraceFile.FullName.Length - nettraceExtension.Length) + ".etlx";
                    PrintMessage($"Creating ETLX file {etlFileName} from {commandLineOptions.TraceFile.FullName}");
                    TraceLog.CreateFromEventPipeDataFile(commandLineOptions.TraceFile.FullName, etlFileName);
                }
            }

            string lttngExtension = ".trace.zip";

            if (commandLineOptions.TraceFile.FullName.EndsWith(lttngExtension))
            {
                etlFileName = commandLineOptions.TraceFile.FullName.Substring(0, commandLineOptions.TraceFile.FullName.Length - lttngExtension.Length) + ".etlx";
                PrintMessage($"Creating ETLX file {etlFileName} from {commandLineOptions.TraceFile.FullName}");
                TraceLog.CreateFromLttngTextDataFile(commandLineOptions.TraceFile.FullName, etlFileName);
            }

            UnZipIfNecessary(ref etlFileName, commandLineOptions.BasicProgressMessages ? Console.Out : new StringWriter());

            using (var traceLog = TraceLog.OpenOrConvert(etlFileName))
            {
                if ((!commandLineOptions.Pid.HasValue && commandLineOptions.ProcessName == null) && traceLog.Processes.Count != 1)
                {
                    PrintError("Trace file contains multiple processes to distinguish between");
                    PrintOutput("Either a pid or process name from the following list must be specified");
                    foreach (TraceProcess proc in traceLog.Processes)
                    {
                        PrintOutput($"Procname = {proc.Name} Pid = {proc.ProcessID}");
                    }
                    return(1);
                }

                if (commandLineOptions.Pid.HasValue && (commandLineOptions.ProcessName != null))
                {
                    PrintError("--pid and --process-name cannot be specified together");
                    return(-1);
                }

                // For a particular process
                TraceProcess p;
                if (commandLineOptions.Pid.HasValue)
                {
                    p = traceLog.Processes.LastProcessWithID(commandLineOptions.Pid.Value);
                }
                else if (commandLineOptions.ProcessName != null)
                {
                    List <TraceProcess> matchingProcesses = new List <TraceProcess>();
                    foreach (TraceProcess proc in traceLog.Processes)
                    {
                        if (String.Compare(proc.Name, commandLineOptions.ProcessName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            matchingProcesses.Add(proc);
                        }
                    }

                    if (matchingProcesses.Count == 0)
                    {
                        PrintError("Unable to find matching process in trace");
                        return(-1);
                    }
                    if (matchingProcesses.Count > 1)
                    {
                        StringBuilder errorMessage = new StringBuilder();

                        errorMessage.AppendLine("Found multiple matching processes in trace");
                        foreach (TraceProcess proc in matchingProcesses)
                        {
                            errorMessage.AppendLine($"{proc.Name}\tpid={proc.ProcessID}\tCPUMSec={proc.CPUMSec}");
                        }
                        PrintError(errorMessage.ToString());
                        return(-2);
                    }
                    p = matchingProcesses[0];
                }
                else
                {
                    p = traceLog.Processes.First();
                }

                if (!p.EventsInProcess.ByEventType <MethodDetailsTraceData>().Any())
                {
                    PrintError($"No MethodDetails\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-3);
                }

                if (!p.EventsInProcess.ByEventType <GCBulkTypeTraceData>().Any())
                {
                    PrintError($"No BulkType data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-4);
                }

                if (!p.EventsInProcess.ByEventType <ModuleLoadUnloadTraceData>().Any())
                {
                    PrintError($"No managed module load data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-5);
                }

                if (!p.EventsInProcess.ByEventType <MethodJittingStartedTraceData>().Any())
                {
                    PrintError($"No managed jit starting data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-5);
                }

                PgoTraceProcess pgoProcess    = new PgoTraceProcess(p);
                int?            clrInstanceId = commandLineOptions.ClrInstanceId;
                if (!clrInstanceId.HasValue)
                {
                    HashSet <int> clrInstanceIds         = new HashSet <int>();
                    HashSet <int> examinedClrInstanceIds = new HashSet <int>();
                    foreach (var assemblyLoadTrace in p.EventsInProcess.ByEventType <AssemblyLoadUnloadTraceData>())
                    {
                        if (examinedClrInstanceIds.Add(assemblyLoadTrace.ClrInstanceID))
                        {
                            if (pgoProcess.ClrInstanceIsCoreCLRInstance(assemblyLoadTrace.ClrInstanceID))
                            {
                                clrInstanceIds.Add(assemblyLoadTrace.ClrInstanceID);
                            }
                        }
                    }

                    if (clrInstanceIds.Count != 1)
                    {
                        if (clrInstanceIds.Count == 0)
                        {
                            PrintError($"No managed CLR in target process, or per module information could not be loaded from the trace.");
                        }
                        else
                        {
                            // There are multiple clr processes... search for the one that implements
                            int[] clrInstanceIdsArray = clrInstanceIds.ToArray();
                            Array.Sort(clrInstanceIdsArray);
                            StringBuilder errorMessage = new StringBuilder();
                            errorMessage.AppendLine("Multiple CLR instances used in process. Choose one to examine with -clrInstanceID:<id> Valid ids:");
                            foreach (int instanceID in clrInstanceIds)
                            {
                                errorMessage.AppendLine(instanceID.ToString());
                            }
                            PrintError(errorMessage.ToString());
                        }
                        return(-10);
                    }
                    else
                    {
                        clrInstanceId = clrInstanceIds.First();
                    }
                }

                var tsc = new TraceTypeSystemContext(pgoProcess, clrInstanceId.Value, s_logger);

                if (commandLineOptions.VerboseWarnings)
                {
                    PrintWarning($"{traceLog.EventsLost} Lost events");
                }

                bool filePathError = false;
                if (commandLineOptions.Reference != null)
                {
                    foreach (FileInfo fileReference in commandLineOptions.Reference)
                    {
                        if (!File.Exists(fileReference.FullName))
                        {
                            PrintError($"Unable to find reference '{fileReference.FullName}'");
                            filePathError = true;
                        }
                        else
                        {
                            tsc.GetModuleFromPath(fileReference.FullName);
                        }
                    }
                }

                if (filePathError)
                {
                    return(-6);
                }

                if (!tsc.Initialize())
                {
                    return(-12);
                }

                TraceRuntimeDescToTypeSystemDesc idParser = new TraceRuntimeDescToTypeSystemDesc(p, tsc, clrInstanceId.Value);

                SortedDictionary <int, ProcessedMethodData> methodsToAttemptToPrepare = new SortedDictionary <int, ProcessedMethodData>();

                if (commandLineOptions.ProcessR2REvents)
                {
                    foreach (var e in p.EventsInProcess.ByEventType <R2RGetEntryPointTraceData>())
                    {
                        int    parenIndex = e.MethodSignature.IndexOf('(');
                        string retArg     = e.MethodSignature.Substring(0, parenIndex);
                        string paramsArgs = e.MethodSignature.Substring(parenIndex);
                        string methodNameFromEventDirectly = retArg + e.MethodNamespace + "." + e.MethodName + paramsArgs;
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            if (!commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Skipped R2REntryPoint {methodNameFromEventDirectly} due to ClrInstanceID of {e.ClrInstanceID}");
                            continue;
                        }
                        MethodDesc method           = null;
                        string     extraWarningText = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception exception)
                        {
                            extraWarningText = exception.ToString();
                        }

                        if (method == null)
                        {
                            if ((e.MethodNamespace == "dynamicClass") || !commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Unable to parse {methodNameFromEventDirectly} when looking up R2R methods");
                            if (extraWarningText != null)
                            {
                                PrintWarning(extraWarningText);
                            }
                            continue;
                        }

                        if ((e.TimeStampRelativeMSec >= commandLineOptions.ExcludeEventsBefore) && (e.TimeStampRelativeMSec <= commandLineOptions.ExcludeEventsAfter))
                        {
                            methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, method, "R2RLoad"));
                        }
                    }
                }

                // Find all the jitStart events.
                if (commandLineOptions.ProcessJitEvents)
                {
                    foreach (var e in p.EventsInProcess.ByEventType <MethodJittingStartedTraceData>())
                    {
                        int    parenIndex = e.MethodSignature.IndexOf('(');
                        string retArg     = e.MethodSignature.Substring(0, parenIndex);
                        string paramsArgs = e.MethodSignature.Substring(parenIndex);
                        string methodNameFromEventDirectly = retArg + e.MethodNamespace + "." + e.MethodName + paramsArgs;
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            if (!commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Skipped {methodNameFromEventDirectly} due to ClrInstanceID of {e.ClrInstanceID}");
                            continue;
                        }

                        MethodDesc method           = null;
                        string     extraWarningText = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception exception)
                        {
                            extraWarningText = exception.ToString();
                        }

                        if (method == null)
                        {
                            if ((e.MethodNamespace == "dynamicClass") || !commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Unable to parse {methodNameFromEventDirectly}");
                            if (extraWarningText != null)
                            {
                                PrintWarning(extraWarningText);
                            }
                            continue;
                        }

                        if ((e.TimeStampRelativeMSec >= commandLineOptions.ExcludeEventsBefore) && (e.TimeStampRelativeMSec <= commandLineOptions.ExcludeEventsAfter))
                        {
                            methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, method, "JitStart"));
                        }
                    }
                }

                Dictionary <MethodDesc, Dictionary <MethodDesc, int> > callGraph = null;
                Dictionary <MethodDesc, int> exclusiveSamples = null;
                if (commandLineOptions.GenerateCallGraph)
                {
                    HashSet <MethodDesc> methodsListedToPrepare = new HashSet <MethodDesc>();
                    foreach (var entry in methodsToAttemptToPrepare)
                    {
                        methodsListedToPrepare.Add(entry.Value.Method);
                    }

                    callGraph        = new Dictionary <MethodDesc, Dictionary <MethodDesc, int> >();
                    exclusiveSamples = new Dictionary <MethodDesc, int>();
                    // Capture the addresses of jitted code
                    List <ValueTuple <InstructionPointerRange, MethodDesc> > codeLocations = new List <(InstructionPointerRange, MethodDesc)>();
                    foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadTraceData>())
                    {
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            continue;
                        }

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

                        if (method != null)
                        {
                            codeLocations.Add((new InstructionPointerRange(e.MethodStartAddress, e.MethodSize), method));
                        }
                    }
                    foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadVerboseTraceData>())
                    {
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            continue;
                        }

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

                        if (method != null)
                        {
                            codeLocations.Add((new InstructionPointerRange(e.MethodStartAddress, e.MethodSize), 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)
                                {
                                    codeLocations.Add((new InstructionPointerRange(module.ImageBase + (ulong)runtimeFunction.StartAddress, runtimeFunction.Size), methodEntry.Key));
                                }
                            }
                        }
                        catch { }
                    }

                    InstructionPointerRange[] instructionPointerRanges = new InstructionPointerRange[codeLocations.Count];
                    MethodDesc[] methods = new MethodDesc[codeLocations.Count];
                    for (int i = 0; i < codeLocations.Count; i++)
                    {
                        instructionPointerRanges[i] = codeLocations[i].Item1;
                        methods[i] = codeLocations[i].Item2;
                    }

                    Array.Sort(instructionPointerRanges, methods);

                    foreach (var e in p.EventsInProcess.ByEventType <SampledProfileTraceData>())
                    {
                        var callstack = e.CallStack();
                        if (callstack == null)
                        {
                            continue;
                        }

                        ulong      address1         = callstack.CodeAddress.Address;
                        MethodDesc topOfStackMethod = LookupMethodByAddress(address1);
                        MethodDesc nextMethod       = null;
                        if (callstack.Caller != null)
                        {
                            ulong address2 = callstack.Caller.CodeAddress.Address;
                            nextMethod = LookupMethodByAddress(address2);
                        }

                        if (topOfStackMethod != null)
                        {
                            if (!methodsListedToPrepare.Contains(topOfStackMethod))
                            {
                                methodsListedToPrepare.Add(topOfStackMethod);
                                methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, topOfStackMethod, "SampleMethod"));
                            }

                            if (exclusiveSamples.TryGetValue(topOfStackMethod, out int count))
                            {
                                exclusiveSamples[topOfStackMethod] = count + 1;
                            }
                            else
                            {
                                exclusiveSamples[topOfStackMethod] = 1;
                            }
                        }

                        if (topOfStackMethod != null && nextMethod != null)
                        {
                            if (!methodsListedToPrepare.Contains(nextMethod))
                            {
                                methodsListedToPrepare.Add(nextMethod);
                                methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, nextMethod, "SampleMethodCaller"));
                            }

                            if (!callGraph.TryGetValue(nextMethod, out var innerDictionary))
                            {
                                innerDictionary       = new Dictionary <MethodDesc, int>();
                                callGraph[nextMethod] = innerDictionary;
                            }
                            if (innerDictionary.TryGetValue(topOfStackMethod, out int count))
                            {
                                innerDictionary[topOfStackMethod] = count + 1;
                            }
                            else
                            {
                                innerDictionary[topOfStackMethod] = 1;
                            }
                        }
                    }

                    MethodDesc LookupMethodByAddress(ulong address)
                    {
                        int index = Array.BinarySearch(instructionPointerRanges, new InstructionPointerRange(address, 1));

                        if (index >= 0)
                        {
                            return(methods[index]);
                        }
                        else
                        {
                            index = ~index;
                            if (index >= instructionPointerRanges.Length)
                            {
                                return(null);
                            }

                            if (instructionPointerRanges[index].StartAddress < address)
                            {
                                if (instructionPointerRanges[index].EndAddress > address)
                                {
                                    return(methods[index]);
                                }
                            }

                            if (index == 0)
                            {
                                return(null);
                            }

                            index--;

                            if (instructionPointerRanges[index].StartAddress < address)
                            {
                                if (instructionPointerRanges[index].EndAddress > address)
                                {
                                    return(methods[index]);
                                }
                            }

                            return(null);
                        }
                    }
                }

                Dictionary <MethodDesc, MethodChunks> instrumentationDataByMethod = new Dictionary <MethodDesc, MethodChunks>();

                foreach (var e in p.EventsInProcess.ByEventType <JitInstrumentationDataVerboseTraceData>())
                {
                    AddToInstrumentationData(e.ClrInstanceID, e.MethodID, e.MethodFlags, e.Data);
                }
                foreach (var e in p.EventsInProcess.ByEventType <JitInstrumentationDataTraceData>())
                {
                    AddToInstrumentationData(e.ClrInstanceID, e.MethodID, e.MethodFlags, e.Data);
                }

                // Local function used with the above two loops as the behavior is supposed to be identical
                void AddToInstrumentationData(int eventClrInstanceId, long methodID, int methodFlags, byte[] data)
                {
                    if (eventClrInstanceId != clrInstanceId.Value)
                    {
                        return;
                    }

                    MethodDesc method = null;

                    try
                    {
                        method = idParser.ResolveMethodID(methodID, commandLineOptions.VerboseWarnings);
                    }
                    catch (Exception)
                    {
                    }

                    if (method != null)
                    {
                        if (!instrumentationDataByMethod.TryGetValue(method, out MethodChunks perMethodChunks))
                        {
                            perMethodChunks = new MethodChunks();
                            instrumentationDataByMethod.Add(method, perMethodChunks);
                        }
                        const int FinalChunkFlag = unchecked ((int)0x80000000);
                        int       chunkIndex     = methodFlags & ~FinalChunkFlag;
                        if ((chunkIndex != (perMethodChunks.LastChunk + 1)) || perMethodChunks.Done)
                        {
                            instrumentationDataByMethod.Remove(method);
                            return;
                        }
                        perMethodChunks.LastChunk = perMethodChunks.InstrumentationData.Count;
                        perMethodChunks.InstrumentationData.Add(data);
                        if ((methodFlags & FinalChunkFlag) == FinalChunkFlag)
                        {
                            perMethodChunks.Done = true;
                        }
                    }
                }

                if (commandLineOptions.DisplayProcessedEvents)
                {
                    foreach (var entry in methodsToAttemptToPrepare)
                    {
                        MethodDesc method = entry.Value.Method;
                        string     reason = entry.Value.Reason;
                        PrintOutput($"{entry.Value.Millisecond.ToString("F4")} {reason} {method}");
                    }
                }

                PrintMessage($"Done processing input file");

                if (commandLineOptions.OutputFileName == null)
                {
                    return(0);
                }

                // Deduplicate entries
                HashSet <MethodDesc>       methodsInListAlready = new HashSet <MethodDesc>();
                List <ProcessedMethodData> methodsUsedInProcess = new List <ProcessedMethodData>();

                PgoDataLoader pgoDataLoader = new PgoDataLoader(idParser);

                foreach (var entry in methodsToAttemptToPrepare)
                {
                    if (methodsInListAlready.Add(entry.Value.Method))
                    {
                        var methodData = entry.Value;
                        if (commandLineOptions.GenerateCallGraph)
                        {
                            exclusiveSamples.TryGetValue(methodData.Method, out methodData.ExclusiveWeight);
                            callGraph.TryGetValue(methodData.Method, out methodData.WeightedCallData);
                        }
                        if (instrumentationDataByMethod.TryGetValue(methodData.Method, out MethodChunks chunks))
                        {
                            int size = 0;
                            foreach (byte[] arr in chunks.InstrumentationData)
                            {
                                size += arr.Length;
                            }

                            byte[] instrumentationData = new byte[size];
                            int    offset = 0;

                            foreach (byte[] arr in chunks.InstrumentationData)
                            {
                                arr.CopyTo(instrumentationData, offset);
                                offset += arr.Length;
                            }

                            var intDecompressor = new PgoProcessor.PgoEncodedCompressedIntParser(instrumentationData, 0);
                            methodData.InstrumentationData = PgoProcessor.ParsePgoData <TypeSystemEntityOrUnknown>(pgoDataLoader, intDecompressor, true).ToArray();
                        }
                        methodsUsedInProcess.Add(methodData);
                    }
                }

                if (commandLineOptions.FileType.Value == PgoFileType.jittrace)
                {
                    GenerateJittraceFile(commandLineOptions.OutputFileName, methodsUsedInProcess, commandLineOptions.JitTraceOptions);
                }
                else if (commandLineOptions.FileType.Value == PgoFileType.mibc)
                {
                    ILCompiler.MethodProfileData[] methodProfileData = new ILCompiler.MethodProfileData[methodsUsedInProcess.Count];
                    for (int i = 0; i < methodProfileData.Length; i++)
                    {
                        ProcessedMethodData processedData = methodsUsedInProcess[i];
                        methodProfileData[i] = new ILCompiler.MethodProfileData(processedData.Method, ILCompiler.MethodProfilingDataFlags.ReadMethodCode, processedData.ExclusiveWeight, processedData.WeightedCallData, 0xFFFFFFFF, processedData.InstrumentationData);
                    }
                    return(MibcEmitter.GenerateMibcFile(tsc, commandLineOptions.OutputFileName, methodProfileData, commandLineOptions.ValidateOutputFile, commandLineOptions.Uncompressed));
                }
            }
            return(0);
        }