Ejemplo n.º 1
0
 public CodeChunkInfo[] GetCodeChunks()
 {
     return(debugger.Dispatcher.UI(() => {
         var chunks = code.GetCodeChunks();
         var res = new CodeChunkInfo[chunks.Length];
         for (int i = 0; i < chunks.Length; i++)
         {
             res[i] = new CodeChunkInfo(chunks[i].StartAddr, chunks[i].Length);
         }
         return res;
     }));
 }
        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);
        }