private object TranslateParameter(uint value, FunctionCallParameter parameter) { var parameterType = parameter.Type; var size = parameter.NumberOfElements; switch(parameterType) { case FunctionCallParameterType.Ignore: return null; case FunctionCallParameterType.Byte: return (byte)value; case FunctionCallParameterType.Int32: return unchecked((int)value); case FunctionCallParameterType.UInt32: return value; case FunctionCallParameterType.Int16: return (short)value; case FunctionCallParameterType.UInt16: return (ushort)value; case FunctionCallParameterType.String: var done = false; var resultString = new StringBuilder(); while(!done) { var readBytes = bus.ReadBytes(value, SizeOfStringBatch); for(var i = 0; i < readBytes.Length; ++i) { var currentByte = readBytes[i]; if(currentByte == 0) { done = true; break; } if(currentByte >= 32 && currentByte < 127) { resultString.Append(Convert.ToChar(currentByte)); } } value += SizeOfStringBatch; } return resultString.ToString(); case FunctionCallParameterType.ByteArray: return bus.ReadBytes(value, size); case FunctionCallParameterType.Int32Array: var intResult = new int[size]; Buffer.BlockCopy(bus.ReadBytes(value, size * sizeof(int)), 0, intResult, 0, intResult.Length); return intResult; case FunctionCallParameterType.UInt32Array: var uintResult = new uint[size]; Buffer.BlockCopy(bus.ReadBytes(value, size * sizeof(uint)), 0, uintResult, 0, uintResult.Length); return uintResult; default: throw new ArgumentOutOfRangeException(); } }
public void TraceFunction(string name, IEnumerable<FunctionCallParameter> parameters, Action<TranslationCPU, uint, string, IEnumerable<object>> callback, FunctionCallParameter? returnParameter = null, Action<TranslationCPU, uint, string, IEnumerable<object>> returnCallback = null) { if(registeredCallbacks.ContainsKey(name)) { throw new RecoverableException("Function {0} is already being traced.".FormatWith(name)); } cpu.Log(LogLevel.Info, "Going to trace function '{0}'.", name); Symbol symbol; try { var address = cpu.Bus.GetSymbolAddress(name); symbol = cpu.Bus.Lookup.GetSymbolByAddress(address); } catch(RecoverableException) { cpu.Log(LogLevel.Warning, "Symbol {0} not found, exiting.", name); throw; } var traceInfo = new TraceInfo(); traceInfo.Begin = symbol.Start; traceInfo.BeginCallback = (pc) => EvaluateTraceCallback(pc, name, parameters, callback); cpu.AddHook(traceInfo.Begin, traceInfo.BeginCallback); if(returnCallback != null && returnParameter.HasValue) { traceInfo.HasEnd = true; traceInfo.End = (uint)(symbol.End - (symbol.IsThumbSymbol ? 2 : 4)); traceInfo.EndCallback = (pc) => EvaluateTraceCallback(pc, name, new[] { returnParameter.Value }, returnCallback); cpu.Log(LogLevel.Debug, "Address is @ 0x{0:X}, end is @ 0x{1:X}.", traceInfo.Begin, traceInfo.End); cpu.AddHook(traceInfo.End, traceInfo.EndCallback); } else { cpu.Log(LogLevel.Debug, "Address is @ 0x{0:X}, end is not traced.", traceInfo.Begin); } registeredCallbacks[name] = traceInfo; }
private void Execute(ICommandInteraction writer, LiteralToken cpuToken, String functionName, bool traceReturn, int? numberOfParameters) { var cpu = (Arm)monitor.ConvertValueOrThrowRecoverable(cpuToken.Value, typeof(Arm)); var cpuTracer = EnsureTracer(cpu); Type handlerType; IFunctionHandler handler; if(!handlers.TryGetValue(functionName, out handlerType)) { if(numberOfParameters.HasValue) { var paramList = new List<FunctionCallParameter>(); for(var i = 0; i < numberOfParameters; ++i) { paramList.Add(new FunctionCallParameter{ Type = FunctionCallParameterType.UInt32 }); } FunctionCallParameter? returnParameter = null; if(traceReturn) { returnParameter = new FunctionCallParameter{ Type = FunctionCallParameterType.UInt32 }; } var defHandler = new DefaultFunctionHandler(cpu); defHandler.CallParameters = paramList; defHandler.ReturnParameter = returnParameter; handler = defHandler; } else { throw new RecoverableException("Handler for {0} not register. You must provide numberOfParameters to use default handler.".FormatWith(functionName)); } } else { handler = Dynamic.InvokeConstructor(handlerType, cpu); } if(traceReturn) { cpuTracer.TraceFunction(functionName, handler.CallParameters, handler.CallHandler, handler.ReturnParameter, handler.ReturnHandler); } else { cpuTracer.TraceFunction(functionName, handler.CallParameters, handler.CallHandler); } }
private object TranslateParameter(uint value, FunctionCallParameter parameter) { var parameterType = parameter.Type; var size = parameter.NumberOfElements; switch (parameterType) { case FunctionCallParameterType.Ignore: return(null); case FunctionCallParameterType.Byte: return((byte)value); case FunctionCallParameterType.Int32: return(unchecked ((int)value)); case FunctionCallParameterType.UInt32: return(value); case FunctionCallParameterType.Int16: return((short)value); case FunctionCallParameterType.UInt16: return((ushort)value); case FunctionCallParameterType.String: var done = false; var resultString = new StringBuilder(); while (!done) { var readBytes = bus.ReadBytes(value, SizeOfStringBatch); for (var i = 0; i < readBytes.Length; ++i) { var currentByte = readBytes[i]; if (currentByte == 0) { done = true; break; } if (currentByte >= 32 && currentByte < 127) { resultString.Append(Convert.ToChar(currentByte)); } } value += SizeOfStringBatch; } return(resultString.ToString()); case FunctionCallParameterType.ByteArray: return(bus.ReadBytes(value, size)); case FunctionCallParameterType.Int32Array: var intResult = new int[size]; Buffer.BlockCopy(bus.ReadBytes(value, size * sizeof(int)), 0, intResult, 0, intResult.Length); return(intResult); case FunctionCallParameterType.UInt32Array: var uintResult = new uint[size]; Buffer.BlockCopy(bus.ReadBytes(value, size * sizeof(uint)), 0, uintResult, 0, uintResult.Length); return(uintResult); default: throw new ArgumentOutOfRangeException(); } }
public void TraceFunction(string name, IEnumerable<FunctionCallParameter> parameters, Action<TranslationCPU, uint, string, IEnumerable<object>> callback, FunctionCallParameter? returnParameter = null, Action<TranslationCPU, uint, string, IEnumerable<object>> returnCallback = null) { cpu.Log(LogLevel.Info, "Going to trace function '{0}'.", name); //TODO: Make better after #3024 uint address; Symbol symbol; uint? end = null; try { address = cpu.Bus.GetSymbolAddress(name); symbol = cpu.Bus.Lookup.GetSymbolByAddress(address); } catch(RecoverableException) { cpu.Log(LogLevel.Warning, "Symbol {0} not found, exiting.", name); throw; } cpu.AddHook((uint)symbol.Start, new Action<uint>((pc) => EvaluateTraceCallback(pc, name, parameters, callback))); if(returnCallback != null && returnParameter.HasValue) { end = (uint)(symbol.End - (symbol.IsThumbSymbol ? 2 : 4)); cpu.Log(LogLevel.Debug, "Address is @ 0x{0:X}, end is @ 0x{1:X}.", address, end); cpu.AddHook(end.Value, new Action<uint>((pc) => EvaluateTraceCallback(pc, name, new []{ returnParameter.Value }, returnCallback))); } else { cpu.Log(LogLevel.Debug, "Address is @ 0x{0:X}, end is not traced.", address); } registeredCallbacks[name] = Tuple.Create((uint)symbol.Start, end); }