protected string?BuildDelegateMethodName(ClrType targetType, ulong action) { var typeAction = heap.GetObjectType(action); var fieldMethodPtr = typeAction.GetFieldByName("_methodPtr"); var fieldMethodPtrAux = typeAction.GetFieldByName("_methodPtrAux"); var methodPtr = (ulong)(long)fieldMethodPtr.GetValue(action); if (methodPtr == 0) { return(null); } ClrMethod method = runtime.GetMethodByAddress(methodPtr) ?? runtime.GetMethodByAddress((ulong)(long)fieldMethodPtrAux.GetValue(action)); // could happen in case of static method // anonymous method var methodTypeName = method.Type.Name; var targetTypeName = targetType.Name; return((methodTypeName != targetTypeName && targetTypeName != "System.Threading.WaitCallback" && !targetTypeName.StartsWith("System.Action<") // method is implemented by an class inherited from targetType ... or a simple delegate indirection to a static/instance method ? $"({targetTypeName})" : "") + $"{methodTypeName}.{method.Name}"); }
public string ResolveSymbol(ulong address) { using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { foreach (ClrInfo version in target.ClrVersions) { ClrRuntime runtime = target.ClrVersions.Single().CreateRuntime(); string methodSignature = runtime.GetMethodByAddress(address) ?.GetFullSignature(); if (!string.IsNullOrWhiteSpace(methodSignature)) { return(methodSignature); } } } Symbol symbol = this.nativeTarget.ResolveSymbol((ulong)address); if (!string.IsNullOrWhiteSpace(symbol.MethodName)) { return(symbol.ToString()); } return(null); }
private bool TryProcessNearJump(ulong methodPtr, [NotNull] ClrRuntime runtime, [CanBeNull] out ClrMethod methodDescriptor) { Assert.ArgumentNotNull(runtime, "runtime"); try { byte[] bytes = ReadBytes(methodPtr + 1, runtime, 4); uint offset = 0; for (int i = bytes.Length; i > 0; i--) { offset = offset * 256; offset += bytes[i - 1]; } ulong res = methodPtr + 5 + offset; methodDescriptor = runtime.GetMethodByAddress(res); return(true); } catch (Exception) { methodDescriptor = null; return(false); } }
private static Translator GetTranslater(ClrRuntime runtime, AddressPrinter addressPrinter) { return(new IntelTranslator { SymbolResolver = (Instruction instruction, long address, ref long offset) => { var addr = (ulong)address; var buffer = new StringWriter(); addressPrinter.Print(buffer, addr); var operand = instruction.Operands.Length > 0 ? instruction.Operands[0] : null; if (operand?.PtrOffset == 0) { return buffer.ToString(); } var method = runtime.GetMethodByAddress(addr); if (method != null) { buffer.Write(" ("); buffer.Write(method.GetFullSignature()); buffer.Write(")"); } return buffer.ToString(); } }); }
private static ClrMethod GetMethod(ClrRuntime runtime, Remote.MethodJitResult result) { if (result.Pointer == null) { return(runtime.GetMethodByHandle((ulong)result.Handle.ToInt64())); } return(runtime.GetMethodByAddress((ulong)result.Pointer.Value.ToInt64())); }
public override bool TryGetSymbolCore(ulong address, out SymbolResolverResult result) { const ulong MIN_ADDR = 0x10000; if (address < MIN_ADDR) { result = default; return(false); } string name; name = clrRuntime.GetJitHelperFunctionName(address); if (!(name is null)) { result = new SymbolResolverResult(SymbolKind.Function, name, address); return(true); } name = clrRuntime.GetMethodTableName(address); if (!(name is null)) { result = new SymbolResolverResult(SymbolKind.Data, "methodtable(" + name + ")", address); return(true); } var method = clrRuntime.GetMethodByAddress(address); if (method is null && (address & ((uint)clrRuntime.PointerSize - 1)) == 0) { if (clrRuntime.ReadPointer(address, out ulong newAddress) && newAddress >= MIN_ADDR) { method = clrRuntime.GetMethodByAddress(newAddress); } } if (!(method is null)) { result = new SymbolResolverResult(SymbolKind.Function, method.ToString(), address); return(true); } result = default; return(false); }
private Tuple <ulong, uint, uint> GetClrRuntimeInstructionPointerInfo(Tuple <int, ulong> input) { int runtimeId = input.Item1; ulong instructionPointer = input.Item2; ClrRuntime clrRuntime = runtimesCache[runtimeId]; ClrMethod method = clrRuntime.GetMethodByAddress(instructionPointer); ClrModule clrModule = method.Type.Module; return(Tuple.Create(clrModule.ImageBase, method.MetadataToken, FindIlOffset(method, instructionPointer))); }
private static string ResolveSymbol(ClrRuntime runtime, Instruction instruction, long addr, ulong currentMethodAddress) { var operand = instruction.Operands.Length > 0 ? instruction.Operands[0] : null; if (operand?.PtrOffset == 0) { var baseOffset = instruction.PC - currentMethodAddress; return($"L{baseOffset + operand.PtrSegment:x4}"); } return(runtime.GetMethodByAddress(unchecked ((ulong)addr))?.GetFullSignature()); }
private Tuple <string, ulong> ReadClrRuntimeFunctionNameAndDisplacement(Tuple <int, ulong> input) { int runtimeId = input.Item1; ulong address = input.Item2; ClrRuntime clrRuntime = runtimesCache[runtimeId]; ClrMethod method = clrRuntime.GetMethodByAddress(address); ClrModule clrModule = method.Type.Module; string moduleName = clrModule?.Name ?? "???"; string functionName = moduleName + "!" + method; ulong displacement = address - method.NativeCode; return(Tuple.Create(functionName, displacement)); }
public override bool TryGetSymbolCore(ulong address, out SymbolResolverResult result) { string name; name = clrRuntime.GetJitHelperFunctionName(address); if (name != null) { result = new SymbolResolverResult(SymbolKind.Function, name, address); return(true); } name = clrRuntime.GetMethodTableName(address); if (name != null) { result = new SymbolResolverResult(SymbolKind.Data, "methodtable(" + name + ")", address); return(true); } var method = clrRuntime.GetMethodByAddress(address); if (method == null && address >= 0x10000) { if (clrRuntime.ReadPointer(address, out ulong newAddress)) { method = clrRuntime.GetMethodByAddress(newAddress); } } if (method != null) { result = new SymbolResolverResult(SymbolKind.Function, method.ToString(), method.NativeCode); return(true); } result = default; return(false); }
private string GetCalledMethodFromAssemblyOutput(ClrRuntime runtime, string assemblyString) { string hexAddressText = ""; var callLocation = assemblyString.LastIndexOf("call"); var qwordPtrLocation = assemblyString.IndexOf("qword ptr"); var openBracket = assemblyString.IndexOf('('); var closeBracket = assemblyString.IndexOf(')'); if (openBracket != -1 && closeBracket != -1 && closeBracket > openBracket) { // 000007fe`979171fb e800261b5e call mscorlib_ni+0x499800 (000007fe`f5ac9800) hexAddressText = assemblyString.Substring(openBracket, closeBracket - openBracket) .Replace("(", "") .Replace(")", "") .Replace("`", ""); } else if (callLocation != -1 && qwordPtrLocation != -1) { // TODO have to also deal with: // 000007fe`979f666f 41ff13 call qword ptr [r11] ds:000007fe`978e0050=000007fe978ed260 } else if (callLocation != -1) { // 000007fe`979e6721 e8e2b5ffff call 000007fe`979e1d08 var endOfCallLocation = callLocation + 4; hexAddressText = assemblyString.Substring(endOfCallLocation, assemblyString.Length - endOfCallLocation) .Replace("`", "") .Trim(' '); } ulong actualAddress; if (ulong.TryParse(hexAddressText, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out actualAddress)) { ClrMethod method = runtime.GetMethodByAddress(actualAddress); if (method != null) { return($"Call: {method.GetFullSignature()}"); } else { return($"Call: {actualAddress:x16} -> No matching method found"); } } return($"\"{hexAddressText}\" -> Not a valid hex value"); }
private static string?ResolveSymbol(ClrRuntime runtime, Instruction instruction, long addr, ulong currentMethodAddress) { var operand = instruction.Operands.Length > 0 ? instruction.Operands[0] : null; if (operand?.PtrOffset == 0) { var lvalue = GetOperandLValue(operand !); if (lvalue == null) { return($"{operand!.RawValue} ; failed to resolve lval ({operand.Size}), please report at https://github.com/ashmind/SharpLab/issues"); } var baseOffset = instruction.PC - currentMethodAddress; return($"L{baseOffset + lvalue:x4}"); } return(runtime.GetMethodByAddress(unchecked ((ulong)addr))?.GetFullSignature()); }
public override void Disassemble(ClrRuntime runtime, TextWriter writer) { var method = runtime.GetMethodByAddress((ulong)Method.MethodHandle.GetFunctionPointer()); if (method == null) { writer.Write("; Failed to load method '"); var declaringType = Method.DeclaringType; if (declaringType != null) { writer.Write(declaringType.FullName); writer.Write('.'); } writer.Write(Method.Name); writer.WriteLine("'."); return; } writer.Write("; "); writer.WriteLine(method.GetFullSignature()); if (method.CompilationType == MethodCompilationType.None) { writer.WriteLine("; Failed to JIT compile this method."); writer.WriteLine("; Please see https://github.com/JeffreyZhao/SeeJit/issues/1 for more details."); return; } var methodAddress = method.HotColdInfo.HotStart; var methodSize = method.HotColdInfo.HotSize; var arch = runtime.ClrInfo.DacInfo.TargetArchitecture == Architecture.X86 ? ArchitectureMode.x86_32 : ArchitectureMode.x86_64; var instructions = Disassemble(methodAddress, methodSize, arch); var maxBytesLength = instructions.Max(i => i.Bytes.Length); var bytesColumnWidth = maxBytesLength * 2 + 2; var addressPrinter = arch == ArchitectureMode.x86_32 ? AddressPrinter.Short : AddressPrinter.Long; var translater = GetTranslater(runtime, addressPrinter); foreach (var ins in instructions) { PrintInstruction(writer, ins, addressPrinter, bytesColumnWidth, translater); } }
private (ClrMethod?method, HotColdRegions?regions) ResolveJitResult(ClrRuntime runtime, MethodJitResult result) { ClrMethod?methodByPointer = null; if (result.Pointer != null) { methodByPointer = runtime.GetMethodByAddress((ulong)result.Pointer.Value.ToInt64()); if (methodByPointer != null) { if (!result.IsSuccess) { return(methodByPointer, null); } var regionsByPointer = FindNonEmptyHotColdInfo(methodByPointer); if (regionsByPointer != null) { return(methodByPointer, regionsByPointer); } } } var methodByHandle = runtime.GetMethodByHandle((ulong)result.Handle.ToInt64()); if (methodByHandle == null) { return(methodByPointer, null); } if (!result.IsSuccess) { return(methodByHandle, null); } var regionsByHandle = FindNonEmptyHotColdInfo(methodByHandle); if (regionsByHandle == null && methodByPointer != null) { return(methodByPointer, null); } return(methodByHandle, regionsByHandle); }
private string BuildTimerCallbackMethodName(ClrRuntime runtime, ulong timerCallbackRef, string methodPtrString) { var heap = runtime.Heap; var methodPtr = GetFieldValue(heap, timerCallbackRef, methodPtrString); if (methodPtr != null) { ClrMethod method = runtime.GetMethodByAddress((ulong)(long)methodPtr); if (method != null) { // look for "this" to figure out the real callback implementor type string thisTypeName = "?"; var thisPtr = GetFieldValue(heap, timerCallbackRef, "_target"); if ((thisPtr != null) && ((ulong)thisPtr) != 0) { ulong thisRef = (ulong)thisPtr; var thisType = heap.GetObjectType(thisRef); if (thisType != null) { thisTypeName = thisType.Name; } } else { thisTypeName = (method.Type != null) ? method.Type.Name : "?"; } return(method.GetFullSignature()); return(string.Format("{0}.{1}", thisTypeName, method.Name)); } else { return(""); } } else { return(""); } }
private string BuildTimerCallbackMethodName(ulong timerCallbackRef) { var methodPtr = GetFieldValue(timerCallbackRef, "_methodPtr"); if (methodPtr != null) { var method = _clr.GetMethodByAddress((ulong)(long)methodPtr); if (method != null) { // look for "this" to figure out the real callback implementor type var thisTypeName = "?"; var thisPtr = GetFieldValue(timerCallbackRef, "_target"); if ((thisPtr != null) && ((ulong)thisPtr) != 0) { ulong thisRef = (ulong)thisPtr; var thisType = _heap.GetObjectType(thisRef); if (thisType != null) { thisTypeName = thisType.Name; } } else { thisTypeName = (method.Type != null) ? method.Type.Name : "?"; } return($"{thisTypeName}.{method.Name}"); } else { return(""); } } else { return(""); } }
private string ResolveSymbol(ClrRuntime runtime, Instruction instruction, long addr, ref ulong currentMethodAddress) { var operand = instruction.Operands.Length > 0 ? instruction.Operands[0] : null; if (operand?.PtrOffset == 0) { var baseOffset = instruction.PC - currentMethodAddress; return($"L{baseOffset + operand.PtrSegment:x4}"); } string signature = runtime.GetMethodByAddress(unchecked ((ulong)addr))?.GetFullSignature(); if (!string.IsNullOrWhiteSpace(signature)) { return(signature); } Symbol symbol = this.engine.ResolveNativeSymbol((ulong)addr); if (!string.IsNullOrWhiteSpace(symbol.MethodName)) { return(symbol.ToString()); } return(null); }
private static ClrMethod FindCompiledMethod(ClrRuntime runtime, MethodBase methodInfo) { var method = runtime.GetMethodByAddress((ulong)methodInfo.MethodHandle.GetFunctionPointer()); if (method == null) { return(null); } if (method.CompilationType != MethodCompilationType.None) { return(method); } foreach (var other in method.Type.Methods) { if (other.MetadataToken == method.MetadataToken && other.CompilationType != MethodCompilationType.None) { return(other); } } return(method); }
private static void OnGetMethodName(ClrRuntime runtime, string args) { // Use ClrMD as normal, but ONLY cache the copy of ClrRuntime (this.Runtime). All other // types you get out of ClrMD (such as ClrHeap, ClrTypes, etc) should be discarded and // reobtained every run. ClrHeap heap = runtime.Heap; // Console.WriteLine now writes to the debugger. ClrMDHelper helper = new ClrMDHelper(runtime); try { ulong methodPtr; if (!ulong.TryParse(args.Trim(), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out methodPtr)) { Console.WriteLine("numeric value expected as method pointer"); return; } ClrMethod method = runtime.GetMethodByAddress(methodPtr); if (method != null) { Console.WriteLine($"{method.Type.Name}.{method.Name}"); } else { Console.WriteLine("invalid method pointer."); } } catch (Exception x) { Console.WriteLine(x.Message); } }
private bool GetReferencedAddressToMethodName(out ulong refAddress, out uint codeSize, out string name, Instruction instruction, ClrRuntime runtime) { name = null; refAddress = 0; codeSize = 0; bool isAddressOk = false; for (int i = 0; i < instruction.OpCount; i++) { switch (instruction.GetOpKind(i)) { case OpKind.NearBranch16: case OpKind.NearBranch32: case OpKind.NearBranch64: refAddress = instruction.NearBranchTarget; isAddressOk = refAddress > ushort.MaxValue; break; case OpKind.Immediate64: refAddress = instruction.GetImmediate(i); isAddressOk = refAddress > ushort.MaxValue; break; case OpKind.Memory64: refAddress = instruction.MemoryAddress64; isAddressOk = refAddress > ushort.MaxValue; break; case OpKind.Memory when instruction.IsIPRelativeMemoryOperand: refAddress = instruction.IPRelativeMemoryAddress; isAddressOk = refAddress > ushort.MaxValue; break; case OpKind.Memory: refAddress = instruction.MemoryDisplacement; isAddressOk = refAddress > ushort.MaxValue; break; } } if (refAddress == 0) { return(false); } var jitHelperFunctionName = runtime.GetJitHelperFunctionName(refAddress); if (string.IsNullOrWhiteSpace(jitHelperFunctionName) == false) { name = jitHelperFunctionName; return(true); } var methodTableName = runtime.GetMethodTableName(refAddress); if (string.IsNullOrWhiteSpace(methodTableName) == false) { name = methodTableName; return(true); } var methodDescriptor = runtime.GetMethodByHandle(refAddress); if (methodDescriptor != null) { name = methodDescriptor.Name; refAddress = methodDescriptor.HotColdInfo.HotStart; codeSize = methodDescriptor.HotColdInfo.HotSize; return(true); } var methodCall = runtime.GetMethodByAddress(refAddress); if (methodCall != null && string.IsNullOrWhiteSpace(methodCall.Name) == false) { name = methodCall.Name; refAddress = methodCall.HotColdInfo.HotStart; codeSize = methodCall.HotColdInfo.HotSize; return(true); } if (methodCall == null) { if (runtime.ReadPointer(refAddress, out ulong newAddress) && newAddress > ushort.MaxValue) { methodCall = runtime.GetMethodByAddress(newAddress); } if (methodCall is null) { return(false); } name = methodCall.Name; refAddress = methodCall.HotColdInfo.HotStart; codeSize = methodCall.HotColdInfo.HotSize; return(true); } return(false); }
/// <summary> /// Attempts to get a ClrMethod for the given instruction pointer. This will return NULL if the /// given instruction pointer is not within any managed method. /// </summary> /// <param name="ip">The ip.</param> /// <returns>IClrMethod.</returns> /// <inheritdoc /> public IClrMethod GetMethodByAddress(ulong ip) => Converter.Convert(Runtime.GetMethodByAddress(ip));