/// <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(); }
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; } }
/// <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(); }