Ejemplo n.º 1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="kind">Code kind</param>
 /// <param name="optimization">Optimization kind</param>
 /// <param name="blocks">All blocks to disassemble</param>
 /// <param name="codeInfo">Extra code info or null</param>
 /// <param name="methodName">Method name or null</param>
 public DbgDotNetNativeCode(NativeCodeKind kind, NativeCodeOptimization optimization, DbgDotNetNativeCodeBlock[] blocks, NativeCodeInfo codeInfo, string methodName)
 {
     Kind         = kind;
     Optimization = optimization;
     Blocks       = blocks ?? throw new ArgumentNullException(nameof(blocks));
     CodeInfo     = codeInfo;
     MethodName   = methodName;
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="kind">Code kind</param>
 /// <param name="optimization">Optimization kind</param>
 /// <param name="blocks">All blocks to disassemble</param>
 /// <param name="codeInfo">Extra code info or null</param>
 /// <param name="variableInfo">Variable info or null</param>
 /// <param name="methodName">Method name or null</param>
 /// <param name="moduleName">Module name or null</param>
 public NativeCode(NativeCodeKind kind, NativeCodeOptimization optimization, NativeCodeBlock[] blocks, NativeCodeInfo codeInfo, NativeVariableInfo[] variableInfo, string methodName, string moduleName)
 {
     Kind         = kind;
     Optimization = optimization;
     Blocks       = blocks ?? throw new ArgumentNullException(nameof(blocks));
     CodeInfo     = codeInfo;
     VariableInfo = variableInfo;
     MethodName   = methodName;
     ModuleName   = moduleName;
 }
        bool TryGetNativeCodeCore(CorCode code, DmdMethodBase reflectionMethod, out DbgDotNetNativeCode nativeCode)
        {
            nativeCode = default;
            if (code == null)
            {
                return(false);
            }

            var process = code.Function?.Module?.Process;

            if (process == null)
            {
                return(false);
            }

            // The returned chunks are sorted
            var chunks = code.GetCodeChunks();

            if (chunks.Length == 0)
            {
                return(false);
            }

            int totalLen = 0;

            foreach (var chunk in chunks)
            {
                totalLen += (int)chunk.Length;
            }
            var allCodeBytes = new byte[totalLen];
            int currentPos   = 0;

            foreach (var chunk in chunks)
            {
                int hr = process.ReadMemory(chunk.StartAddr, allCodeBytes, currentPos, (int)chunk.Length, out int sizeRead);
                if (hr < 0 || sizeRead != (int)chunk.Length)
                {
                    return(false);
                }
                currentPos += (int)chunk.Length;
            }
            Debug.Assert(currentPos == totalLen);

            // We must get IL to native mappings before we get var homes, or the var
            // homes array will be empty.
            var map      = code.GetILToNativeMapping();
            var varHomes = code.GetVariables();

            Array.Sort(varHomes, (a, b) => {
                int c = a.StartOffset.CompareTo(b.StartOffset);
                if (c != 0)
                {
                    return(c);
                }
                return(a.Length.CompareTo(b.Length));
            });
            for (int i = 0, chunkIndex = 0, chunkOffset = 0; i < varHomes.Length; i++)
            {
                var startOffset = varHomes[i].StartOffset;
                while (chunkIndex < chunks.Length)
                {
                    if (startOffset < (uint)chunkOffset + chunks[chunkIndex].Length)
                    {
                        break;
                    }
                    chunkOffset += (int)chunks[chunkIndex].Length;
                    chunkIndex++;
                }
                Debug.Assert(chunkIndex < chunks.Length);
                if (chunkIndex >= chunks.Length)
                {
                    varHomes = Array.Empty <VariableHome>();
                    break;
                }
                varHomes[i].StartOffset += chunks[chunkIndex].StartAddr - (uint)chunkOffset;
            }
            Array.Sort(varHomes, (a, b) => {
                int c = a.SlotIndex.CompareTo(b.SlotIndex);
                if (c != 0)
                {
                    return(c);
                }
                c = a.ArgumentIndex.CompareTo(b.ArgumentIndex);
                if (c != 0)
                {
                    return(c);
                }
                c = a.StartOffset.CompareTo(b.StartOffset);
                if (c != 0)
                {
                    return(c);
                }
                return(a.Length.CompareTo(b.Length));
            });

            Array.Sort(map, (a, b) => {
                int c = a.nativeStartOffset.CompareTo(b.nativeStartOffset);
                if (c != 0)
                {
                    return(c);
                }
                return(a.nativeEndOffset.CompareTo(b.nativeEndOffset));
            });
            totalLen = 0;
            for (int i = 0; i < chunks.Length; i++)
            {
                chunks[i].StartAddr -= (uint)totalLen;
                totalLen            += (int)chunks[i].Length;
            }
            var   blocks          = new DbgDotNetNativeCodeBlock[map.Length];
            ulong baseAddress     = chunks[0].StartAddr;
            uint  chunkByteOffset = 0;

            for (int i = 0, chunkIndex = 0; i < blocks.Length; i++)
            {
                var  info = map[i];
                bool b    = info.nativeEndOffset <= (uint)allCodeBytes.Length && info.nativeStartOffset <= info.nativeEndOffset && chunkIndex < chunks.Length;
                Debug.Assert(b);
                if (!b)
                {
                    return(false);
                }
                int   codeLen = (int)(info.nativeEndOffset - info.nativeStartOffset);
                var   rawCode = new ArraySegment <byte>(allCodeBytes, (int)info.nativeStartOffset, codeLen);
                ulong address = baseAddress + info.nativeStartOffset;
                if ((CorDebugIlToNativeMappingTypes)info.ilOffset == CorDebugIlToNativeMappingTypes.NO_MAPPING)
                {
                    blocks[i] = new DbgDotNetNativeCodeBlock(NativeCodeBlockKind.Unknown, address, rawCode, -1);
                }
                else if ((CorDebugIlToNativeMappingTypes)info.ilOffset == CorDebugIlToNativeMappingTypes.PROLOG)
                {
                    blocks[i] = new DbgDotNetNativeCodeBlock(NativeCodeBlockKind.Prolog, address, rawCode, -1);
                }
                else if ((CorDebugIlToNativeMappingTypes)info.ilOffset == CorDebugIlToNativeMappingTypes.EPILOG)
                {
                    blocks[i] = new DbgDotNetNativeCodeBlock(NativeCodeBlockKind.Epilog, address, rawCode, -1);
                }
                else
                {
                    blocks[i] = new DbgDotNetNativeCodeBlock(NativeCodeBlockKind.Code, address, rawCode, (int)info.ilOffset);
                }

                chunkByteOffset += (uint)codeLen;
                for (;;)
                {
                    if (chunkIndex >= chunks.Length)
                    {
                        if (i + 1 == blocks.Length)
                        {
                            break;
                        }
                        Debug.Assert(false);
                        return(false);
                    }
                    if (chunkByteOffset < chunks[chunkIndex].Length)
                    {
                        break;
                    }
                    chunkByteOffset -= chunks[chunkIndex].Length;
                    chunkIndex++;
                    if (chunkIndex < chunks.Length)
                    {
                        baseAddress = chunks[chunkIndex].StartAddr;
                    }
                }
            }

            NativeCodeOptimization optimization;

            switch (code.CompilerFlags)
            {
            case CorDebugJITCompilerFlags.CORDEBUG_JIT_DEFAULT:
                optimization = NativeCodeOptimization.Optimized;
                break;

            case CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION:
            case CorDebugJITCompilerFlags.CORDEBUG_JIT_ENABLE_ENC:
                optimization = NativeCodeOptimization.Unoptimized;
                break;

            default:
                Debug.Fail($"Unknown optimization: {code.CompilerFlags}");
                optimization = NativeCodeOptimization.Unknown;
                break;
            }

            NativeCodeInfo codeInfo = null;
            NativeCodeKind codeKind;

            switch (Runtime.Process.Machine)
            {
            case DbgMachine.X64:
            case DbgMachine.X86:
                codeKind = Runtime.Process.Machine == DbgMachine.X86 ? NativeCodeKind.X86_32 : NativeCodeKind.X86_64;
                var x86Variables = CreateVariablesX86(varHomes) ?? Array.Empty <X86Variable>();
                if (x86Variables.Length != 0)
                {
                    codeInfo = new X86NativeCodeInfo(x86Variables);
                }
                break;

            case DbgMachine.Arm:
                codeKind = NativeCodeKind.Arm;
                Debug.Fail("Create variables like x86/x64 code above");
                break;

            case DbgMachine.Arm64:
                codeKind = NativeCodeKind.Arm64;
                Debug.Fail("Create variables like x86/x64 code above");
                break;

            default:
                Debug.Fail($"Unsupported machine: {Runtime.Process.Machine}");
                return(false);
            }

            var methodName = reflectionMethod?.ToString();

            nativeCode = new DbgDotNetNativeCode(codeKind, optimization, blocks, codeInfo, methodName);
            return(true);
        }
 public X86DisassemblyContentProviderFactory(X86DisassemblyContentProviderFactoryDependencies deps, int bitness, DisassemblyContentFormatterOptions formatterOptions, Contracts.Disassembly.ISymbolResolver symbolResolver, string header, NativeCodeOptimization optimization, NativeCodeBlock[] blocks, NativeCodeInfo codeInfo, NativeVariableInfo[] variableInfo, string methodName)
 {
     if (blocks == null)
     {
         throw new ArgumentNullException(nameof(blocks));
     }
     this.deps             = deps ?? throw new ArgumentNullException(nameof(deps));
     this.bitness          = bitness;
     this.formatterOptions = formatterOptions;
     this.symbolResolver   = symbolResolver;
     this.header           = header;
     this.optimization     = optimization;
     this.blocks           = blocks ?? throw new ArgumentNullException(nameof(blocks));
     this.codeInfo         = codeInfo as X86NativeCodeInfo;
     this.variableInfo     = variableInfo;
     this.methodName       = methodName;
 }