/// <summary>
        /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813
        /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156
        /// </summary>
        private void PrintAssemblyCode(ClrMethod method, IList <ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl)
        {
            // This is the first instruction of the JIT'ed (or NGEN'ed) machine code.
            ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min();

            // Unfortunately there's not a great way to get the size of the code, or the end address.
            // You are supposed to do code flow analysis like "uf" in windbg to find the size, but
            // in practice you can use the IL to native mapping:
            ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max();

            var   bufferSize = 500; // per-line
            var   lineOfAssembly = new StringBuilder(bufferSize);
            ulong startOffset = startAddress, endOffset;
            uint  disassemblySize;

            do
            {
                var flags  = DEBUG_DISASM.EFFECTIVE_ADDRESS;
                var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset);
                startOffset = endOffset;
                logger?.Write(lineOfAssembly.ToString());

                if (lineOfAssembly.ToString().Contains(" call ") == false)
                {
                    continue;
                }

                var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString());
                if (string.IsNullOrWhiteSpace(methodCallInfo) == false)
                {
                    logger?.WriteLine(BenchmarkLogKind.Info, $"  {methodCallInfo}");
                }
            } while (disassemblySize > 0 && endOffset <= endAddress);
            logger?.WriteLine();
        }
Example #2
0
        private void DisassembleNative(ILToNativeMap map)
        {
            ulong         nextInstr;
            StringBuilder disasmBuffer = new StringBuilder(512);
            uint          disasmSize;
            ulong         disasmAddress = map.StartAddress;

            while (true)
            {
                int hr = _control.Disassemble(disasmAddress, 0,
                                              disasmBuffer, disasmBuffer.Capacity, out disasmSize,
                                              out nextInstr);
                if (hr != 0)
                {
                    break;
                }
                _context.Write(disasmBuffer.ToString());

                if (nextInstr >= map.EndAddress)
                {
                    break;
                }
                disasmAddress = nextInstr;
            }
        }
Example #3
0
        /// <summary>
        /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813
        /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156
        /// </summary>
        private void PrintAssemblyCode(ClrMethod method, IList<ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl)
        {
            // This is the first instruction of the JIT'ed (or NGEN'ed) machine code.
            ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min();

            // Unfortunately there's not a great way to get the size of the code, or the end address.
            // You are supposed to do code flow analysis like "uf" in windbg to find the size, but
            // in practice you can use the IL to native mapping:
            ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max();

            var bufferSize = 500; // per-line
            var lineOfAssembly = new StringBuilder(bufferSize);
            ulong startOffset = startAddress, endOffset;
            uint disassemblySize;
            do
            {
                var flags = DEBUG_DISASM.EFFECTIVE_ADDRESS;
                var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset);
                startOffset = endOffset;
                logger?.Write(lineOfAssembly.ToString());

                if (lineOfAssembly.ToString().Contains(" call ") == false)
                    continue;

                var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString());
                if (string.IsNullOrWhiteSpace(methodCallInfo) == false)
                    logger?.WriteLine(LogKind.Info, $"  {methodCallInfo}");
            } while (disassemblySize > 0 && endOffset <= endAddress);
            logger?.WriteLine();
        }