예제 #1
0
 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();
     }
 }
예제 #2
0
파일: CPUTracer.cs 프로젝트: rte-se/emul8
        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;
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        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);
        }