Exemple #1
0
        private void DiffR2RMethodsForHeader(ReadyToRunCoreHeader leftHeader, ReadyToRunCoreHeader rightHeader)
        {
            if (!leftHeader.Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out ReadyToRunSection leftSection))
            {
                leftSection = new ReadyToRunSection();
            }
            if (!rightHeader.Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out ReadyToRunSection rightSection))
            {
                rightSection = new ReadyToRunSection();
            }
            ShowDiff(GetR2RMethodMap(_leftDumper.Reader, leftSection), GetR2RMethodMap(_rightDumper.Reader, rightSection), "R2R methods");

            if (_leftDumper.Reader.Composite && _rightDumper.Reader.Composite)
            {
                HashSet <string> allComponentAssemblies = new HashSet <string>(_leftDumper.Reader.ManifestReferenceAssemblies.Keys);
                allComponentAssemblies.UnionWith(_rightDumper.Reader.ManifestReferenceAssemblies.Keys);
                foreach (string assemblyName in allComponentAssemblies.OrderBy(name => name))
                {
                    int leftIndex  = _leftDumper.Reader.ManifestReferenceAssemblies[assemblyName];
                    int rightIndex = _rightDumper.Reader.ManifestReferenceAssemblies[assemblyName];
                    if (leftIndex < 0 || !_leftDumper.Reader.ReadyToRunAssemblyHeaders[leftIndex].Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out leftSection))
                    {
                        leftSection = new ReadyToRunSection();
                    }
                    if (rightIndex < 0 || !_rightDumper.Reader.ReadyToRunAssemblyHeaders[rightIndex].Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out rightSection))
                    {
                        rightSection = new ReadyToRunSection();
                    }
                    ShowDiff(GetR2RMethodMap(_leftDumper.Reader, leftSection), GetR2RMethodMap(_rightDumper.Reader, rightSection), $"{assemblyName}: component R2R methods");
                }
            }
        }
Exemple #2
0
        private void DiffMethodsForModule(ReadyToRunSection leftSection, ReadyToRunSection rightSection)
        {
            if (!TryGetMethods(_leftDumper.Reader, leftSection, out IReadOnlyList <ReadyToRunMethod> leftSectionMethods))
            {
                leftSectionMethods = new List <ReadyToRunMethod>();
            }
            if (!TryGetMethods(_rightDumper.Reader, rightSection, out IReadOnlyList <ReadyToRunMethod> rightSectionMethods))
            {
                rightSectionMethods = new List <ReadyToRunMethod>();
            }

            Dictionary <string, ReadyToRunMethod> leftMethods = new Dictionary <string, ReadyToRunMethod>(leftSectionMethods
                                                                                                          .Select(method => new KeyValuePair <string, ReadyToRunMethod>(method.SignatureString, method)));
            Dictionary <string, ReadyToRunMethod> rightMethods = new Dictionary <string, ReadyToRunMethod>(rightSectionMethods
                                                                                                           .Select(method => new KeyValuePair <string, ReadyToRunMethod>(method.SignatureString, method)));
            Dictionary <string, MethodPair> commonMethods = new Dictionary <string, MethodPair>(leftMethods
                                                                                                .Select(kvp => new KeyValuePair <string, MethodPair>(kvp.Key,
                                                                                                                                                     new MethodPair(kvp.Value, rightMethods.TryGetValue(kvp.Key, out ReadyToRunMethod rightMethod) ? rightMethod : null)))
                                                                                                .Where(kvp => kvp.Value.RightMethod != null));

            if (_leftDumper.Options.DiffHideSameDisasm)
            {
                commonMethods = new Dictionary <string, MethodPair>(HideMethodsWithSameDisassembly(commonMethods));
            }
            DumpCommonMethods(_leftDumper, leftSection, commonMethods);
            DumpCommonMethods(_rightDumper, rightSection, commonMethods);
        }
Exemple #3
0
        /// <summary>
        /// Returns true if the name or value of the ReadyToRunSectionType of <param>section</param> matches <param>query</param>
        /// </summary>
        /// <remarks>Case-insensitive</remarks>
        private bool Match(ReadyToRunSection section, string query)
        {
            int    queryInt;
            bool   isNum    = ArgStringToInt(query, out queryInt);
            string typeName = Enum.GetName(typeof(ReadyToRunSectionType), section.Type);

            return((isNum && (int)section.Type == queryInt) || typeName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0);
        }
 public static void WriteTo(this ReadyToRunSection theThis, TextWriter writer, DumpOptions options)
 {
     writer.WriteLine($"Type:  {Enum.GetName(typeof(ReadyToRunSectionType), theThis.Type)} ({theThis.Type:D})");
     if (!options.Naked)
     {
         writer.WriteLine($"RelativeVirtualAddress: 0x{theThis.RelativeVirtualAddress:X8}");
     }
     writer.WriteLine($"Size: {theThis.Size} bytes");
 }
Exemple #5
0
        /// <summary>
        /// Dump the subset of methods common to both sides of the diff to the given dumper.
        /// </summary>
        /// <param name="dumper">Output dumper to use</param>
        /// <param name="signatureFilter">Set of common signatures of methods to dump</param>
        private void DumpCommonMethods(Dumper dumper, ReadyToRunSection section, Dictionary <string, MethodPair> signatureFilter)
        {
            if (!TryGetMethods(dumper.Reader, section, out IReadOnlyList <ReadyToRunMethod> sectionMethods))
            {
                IEnumerable <ReadyToRunMethod> filteredMethods = sectionMethods
                                                                 .Where(method => signatureFilter.ContainsKey(method.SignatureString))
                                                                 .OrderBy(method => method.SignatureString);

                foreach (ReadyToRunMethod method in filteredMethods)
                {
                    dumper.DumpMethod(method);
                }
            }
        }
Exemple #6
0
        private bool TryGetMethods(ReadyToRunReader reader, ReadyToRunSection section, out IReadOnlyList <ReadyToRunMethod> methods)
        {
            int assemblyIndex = reader.GetAssemblyIndex(section);

            if (assemblyIndex == -1)
            {
                methods = null;
                return(false);
            }
            else
            {
                methods = reader.ReadyToRunAssemblies[assemblyIndex].Methods;
                return(true);
            }
        }
Exemple #7
0
        /// <summary>
        /// Read the R2R method map for a given R2R image.
        /// </summary>
        /// <param name="reader">R2R image to scan</param>
        /// <returns></returns>
        private Dictionary <string, int> GetR2RMethodMap(ReadyToRunReader reader, ReadyToRunSection section)
        {
            Dictionary <string, int> methodMap = new Dictionary <string, int>();

            if (TryGetMethods(reader, section, out IReadOnlyList <ReadyToRunMethod> sectionMethods))
            {
                foreach (ReadyToRunMethod method in sectionMethods)
                {
                    int size = method.RuntimeFunctions.Sum(rf => rf.Size);
                    methodMap.Add(method.SignatureString, size);
                }
            }

            return(methodMap);
        }
Exemple #8
0
        /// <summary>
        /// Dumps one R2RSection
        /// </summary>
        internal override void DumpSection(ReadyToRunSection section)
        {
            WriteSubDivider();
            section.WriteTo(_writer, _options);

            if (_options.Raw)
            {
                DumpBytes(section.RelativeVirtualAddress, (uint)section.Size);
                SkipLine();
            }
            if (_options.SectionContents)
            {
                DumpSectionContents(section);
                SkipLine();
            }
        }
Exemple #9
0
        /// <summary>
        /// Public API runs all available diff algorithms in sequence.
        /// </summary>
        public void Run()
        {
            DiffTitle();
            DiffPESections();
            DiffR2RSections();
            DiffR2RMethods();

            if (!_leftDumper.Reader.ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out ReadyToRunSection leftSection))
            {
                leftSection = new ReadyToRunSection();
            }
            if (!_rightDumper.Reader.ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out ReadyToRunSection rightSection))
            {
                rightSection = new ReadyToRunSection();
            }

            DiffMethodsForModule(leftSection, rightSection);

            if (_leftDumper.Reader.Composite && _rightDumper.Reader.Composite)
            {
                HashSet <string> allComponentAssemblies = new HashSet <string>(_leftDumper.Reader.ManifestReferenceAssemblies.Keys);
                allComponentAssemblies.UnionWith(_rightDumper.Reader.ManifestReferenceAssemblies.Keys);
                foreach (string assemblyName in allComponentAssemblies.OrderBy(name => name))
                {
                    int leftIndex  = _leftDumper.Reader.ManifestReferenceAssemblies[assemblyName];
                    int rightIndex = _rightDumper.Reader.ManifestReferenceAssemblies[assemblyName];

                    if (leftIndex < 0 || !_leftDumper.Reader.ReadyToRunAssemblyHeaders[leftIndex].Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out leftSection))
                    {
                        leftSection = new ReadyToRunSection();
                    }
                    if (rightIndex < 0 || !_rightDumper.Reader.ReadyToRunAssemblyHeaders[rightIndex].Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out rightSection))
                    {
                        rightSection = new ReadyToRunSection();
                    }
                    _writer.WriteLine($@"{assemblyName}: component method diff");
                    DiffMethodsForModule(leftSection, rightSection);
                }
            }
        }
Exemple #10
0
        internal override void DumpSectionContents(ReadyToRunSection section)
        {
            switch (section.Type)
            {
            case ReadyToRunSectionType.AvailableTypes:
                if (!_options.Naked)
                {
                    uint            availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    availableTypesParser        = new NativeParser(_r2r.Image, availableTypesSectionOffset);
                    NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size));
                    _writer.WriteLine(availableTypes.ToString());
                }

                if (_r2r.AvailableTypes.TryGetValue(section, out List <string> sectionTypes))
                {
                    _writer.WriteLine();
                    foreach (string name in sectionTypes)
                    {
                        _writer.WriteLine(name);
                    }
                }
                break;

            case ReadyToRunSectionType.MethodDefEntryPoints:
                if (!_options.Naked)
                {
                    NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress));
                    _writer.Write(methodEntryPoints.ToString());
                }

                if (_r2r.Methods.TryGetValue(section, out List <ReadyToRunMethod> sectionMethods))
                {
                    _writer.WriteLine();
                    foreach (ReadyToRunMethod method in sectionMethods)
                    {
                        _writer.WriteLine($@"{MetadataTokens.GetToken(method.MethodHandle):X8}: {method.SignatureString}");
                    }
                }
                break;

            case ReadyToRunSectionType.InstanceMethodEntryPoints:
                if (!_options.Naked)
                {
                    uint            instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    instanceParser        = new NativeParser(_r2r.Image, instanceSectionOffset);
                    NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size));
                    _writer.Write(instMethodEntryPoints.ToString());
                    _writer.WriteLine();
                }
                foreach (InstanceMethod instanceMethod in _r2r.InstanceMethods)
                {
                    _writer.WriteLine($@"0x{instanceMethod.Bucket:X2} -> {instanceMethod.Method.SignatureString}");
                }
                break;

            case ReadyToRunSectionType.RuntimeFunctions:
                int rtfOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    int endRva   = -1;
                    if (_r2r.Machine == Machine.Amd64)
                    {
                        endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    }
                    int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    _writer.WriteLine($"Index: {rtfIndex}");
                    _writer.WriteLine($"        StartRva: 0x{startRva:X8}");
                    if (endRva != -1)
                    {
                        _writer.WriteLine($"        EndRva: 0x{endRva:X8}");
                    }
                    _writer.WriteLine($"        UnwindRva: 0x{unwindRva:X8}");
                    rtfIndex++;
                }
                break;

            case ReadyToRunSectionType.CompilerIdentifier:
                _writer.WriteLine(_r2r.CompilerIdentifier);
                break;

            case ReadyToRunSectionType.ImportSections:
                if (_options.Naked)
                {
                    DumpNakedImportSections();
                }
                else
                {
                    foreach (ReadyToRunImportSection importSection in _r2r.ImportSections)
                    {
                        importSection.WriteTo(_writer);
                        if (_options.Raw && importSection.Entries.Count != 0)
                        {
                            if (importSection.SectionRVA != 0)
                            {
                                _writer.WriteLine("Section Bytes:");
                                DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize);
                            }
                            if (importSection.SignatureRVA != 0)
                            {
                                _writer.WriteLine("Signature Bytes:");
                                DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int));
                            }
                            if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryDataSize != 0)
                            {
                                _writer.WriteLine("AuxiliaryData Bytes:");
                                DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize);
                            }
                        }
                        foreach (ReadyToRunImportSection.ImportSectionEntry entry in importSection.Entries)
                        {
                            entry.WriteTo(_writer, _options);
                            _writer.WriteLine();
                        }
                        _writer.WriteLine();
                    }
                }
                break;

            case ReadyToRunSectionType.ManifestMetadata:
                int assemblyRefCount = 0;
                if (!_r2r.Composite)
                {
                    MetadataReader globalReader = _r2r.GetGlobalMetadataReader();
                    assemblyRefCount = globalReader.GetTableRowCount(TableIndex.AssemblyRef) + 1;
                    _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):");
                    for (int assemblyRefIndex = 1; assemblyRefIndex < assemblyRefCount; assemblyRefIndex++)
                    {
                        AssemblyReference assemblyRef     = globalReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex));
                        string            assemblyRefName = globalReader.GetString(assemblyRef.Name);
                        _writer.WriteLine($"[ID 0x{assemblyRefIndex:X2}]: {assemblyRefName}");
                    }
                }

                _writer.WriteLine($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count} entries):");
                int manifestAsmIndex = 0;
                foreach (string manifestReferenceAssembly in _r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key))
                {
                    _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 1:X2}]: {manifestReferenceAssembly}");
                    manifestAsmIndex++;
                }
                break;

            case ReadyToRunSectionType.AttributePresence:
                int attributesStartOffset     = _r2r.GetOffset(section.RelativeVirtualAddress);
                int attributesEndOffset       = attributesStartOffset + section.Size;
                NativeCuckooFilter attributes = new NativeCuckooFilter(_r2r.Image, attributesStartOffset, attributesEndOffset);
                _writer.WriteLine("Attribute presence filter");
                _writer.WriteLine(attributes.ToString());
                break;

            case ReadyToRunSectionType.InliningInfo:
                int iiOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int iiEndOffset = iiOffset + section.Size;
                InliningInfoSection inliningInfoSection = new InliningInfoSection(_r2r, iiOffset, iiEndOffset);
                _writer.WriteLine(inliningInfoSection.ToString());
                break;

            case ReadyToRunSectionType.InliningInfo2:
                int ii2Offset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int ii2EndOffset = ii2Offset + section.Size;
                InliningInfoSection2 inliningInfoSection2 = new InliningInfoSection2(_r2r, ii2Offset, ii2EndOffset);
                _writer.WriteLine(inliningInfoSection2.ToString());
                break;

            case ReadyToRunSectionType.OwnerCompositeExecutable:
                int oceOffset = _r2r.GetOffset(section.RelativeVirtualAddress);
                if (_r2r.Image[oceOffset + section.Size - 1] != 0)
                {
                    R2RDump.WriteWarning("String is not zero-terminated");
                }
                string ownerCompositeExecutable = Encoding.UTF8.GetString(_r2r.Image, oceOffset, section.Size - 1);     // exclude the zero terminator
                _writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable.ToEscapedString());
                break;
            }
        }
Exemple #11
0
 abstract internal void DumpSectionContents(ReadyToRunSection section);
Exemple #12
0
        internal override void DumpSectionContents(ReadyToRunSection section)
        {
            switch (section.Type)
            {
            case ReadyToRunSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES:
                if (!_options.Naked)
                {
                    uint            availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    availableTypesParser        = new NativeParser(_r2r.Image, availableTypesSectionOffset);
                    NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size));
                    _writer.WriteLine(availableTypes.ToString());
                }

                foreach (string name in _r2r.AvailableTypes)
                {
                    _writer.WriteLine(name);
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS:
                if (!_options.Naked)
                {
                    NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress));
                    _writer.Write(methodEntryPoints.ToString());
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS:
                if (!_options.Naked)
                {
                    uint            instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    instanceParser        = new NativeParser(_r2r.Image, instanceSectionOffset);
                    NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size));
                    _writer.Write(instMethodEntryPoints.ToString());
                    _writer.WriteLine();
                }
                foreach (InstanceMethod instanceMethod in _r2r.InstanceMethods)
                {
                    _writer.WriteLine($@"0x{instanceMethod.Bucket:X2} -> {instanceMethod.Method.SignatureString}");
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS:
                int rtfOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    int endRva   = -1;
                    if (_r2r.Machine == Machine.Amd64)
                    {
                        endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    }
                    int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    _writer.WriteLine($"Index: {rtfIndex}");
                    _writer.WriteLine($"\tStartRva: 0x{startRva:X8}");
                    if (endRva != -1)
                    {
                        _writer.WriteLine($"\tEndRva: 0x{endRva:X8}");
                    }
                    _writer.WriteLine($"\tUnwindRva: 0x{unwindRva:X8}");
                    rtfIndex++;
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER:
                _writer.WriteLine(_r2r.CompilerIdentifier);
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS:
                if (_options.Naked)
                {
                    DumpNakedImportSections();
                }
                else
                {
                    foreach (ReadyToRunImportSection importSection in _r2r.ImportSections)
                    {
                        importSection.WriteTo(_writer);
                        if (_options.Raw && importSection.Entries.Count != 0)
                        {
                            if (importSection.SectionRVA != 0)
                            {
                                _writer.WriteLine("Section Bytes:");
                                DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize);
                            }
                            if (importSection.SignatureRVA != 0)
                            {
                                _writer.WriteLine("Signature Bytes:");
                                DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int));
                            }
                            if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryDataSize != 0)
                            {
                                _writer.WriteLine("AuxiliaryData Bytes:");
                                DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize);
                            }
                        }
                        foreach (ReadyToRunImportSection.ImportSectionEntry entry in importSection.Entries)
                        {
                            entry.WriteTo(_writer, _options);
                            _writer.WriteLine();
                        }
                        _writer.WriteLine();
                    }
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA:
                int assemblyRefCount = _r2r.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef);
                _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):");
                for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++)
                {
                    AssemblyReference assemblyRef     = _r2r.MetadataReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex));
                    string            assemblyRefName = _r2r.MetadataReader.GetString(assemblyRef.Name);
                    _writer.WriteLine($"[ID 0x{assemblyRefIndex:X2}]: {assemblyRefName}");
                }

                _writer.WriteLine($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count()} entries):");
                int manifestAsmIndex = 0;
                foreach (string manifestReferenceAssembly in _r2r.ManifestReferenceAssemblies)
                {
                    _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {manifestReferenceAssembly}");
                    manifestAsmIndex++;
                }
                break;

            case ReadyToRunSection.SectionType.READYTORUN_SECTION_ATTRIBUTEPRESENCE:
                int attributesStartOffset     = _r2r.GetOffset(section.RelativeVirtualAddress);
                int attributesEndOffset       = attributesStartOffset + section.Size;
                NativeCuckooFilter attributes = new NativeCuckooFilter(_r2r.Image, attributesStartOffset, attributesEndOffset);
                _writer.WriteLine("Attribute presence filter");
                _writer.WriteLine(attributes.ToString());
                break;
            }
        }