public void PrintStatistics() { if (IsEnabled) { DLog.Info(DContext.CompilerCodeGenerator, "Compiler cache: {0} hits and {1} misses.", statCacheHits, statCacheMisses); } }
public void Start() { // Start JDWP monitor jdwpMonitor = new JdwpMonitor(device); jdwpMonitor.Start(); // Wait for initial update jdwpMonitor.WaitForInitialUpdate(); jdwpMonitor.ProcessAdded += (s, x) => { DLog.Debug(DContext.VSDebuggerLauncher, "JDWP Process added {0}", x.Data); Task.Factory.StartNew(() => OnDebuggableProcessAdded(device, x.Data)); }; jdwpMonitor.ProcessRemoved += (s, x) => DLog.Info(DContext.VSDebuggerLauncher, "JDWP process removed {0}", x.Data); }
private void RemoveBehavior(ReferenceTypeId refTypeId, string signature) { int prevEventId; if (_eventRequests.TryRemove(refTypeId, out prevEventId)) { DLog.Info(DContext.DebuggerLibDebugger, "clearing exception event: " + signature); Debugger.EventRequest.ClearAsync(Jdwp.EventKind.Exception, prevEventId) .Await(DalvikProcess.VmTimeout); } }
private void SetupBehavior(ReferenceTypeId refTypeId, bool stopOnThrow, bool stopUncaught, string signature) { // set the event DLog.Info(DContext.DebuggerLibDebugger, "requesting exception event {0}: stopOnThrow: {1} stopUncaught: {2}", signature, stopOnThrow, stopUncaught); var modifier = new ExceptionOnlyModifier(refTypeId, stopOnThrow, stopUncaught); var eventId = Debugger.EventRequest.SetAsync(Jdwp.EventKind.Exception, Jdwp.SuspendPolicy.All, modifier) .Await(DalvikProcess.VmTimeout); // remove previous event, if any. int?prevEventId = null; _eventRequests.AddOrUpdate(refTypeId, eventId, (key, prev) => { prevEventId = prev; return(eventId); }); if (prevEventId.HasValue) { Debugger.EventRequest.ClearAsync(Jdwp.EventKind.Exception, prevEventId.Value) .Await(DalvikProcess.VmTimeout); } }
private void AddPropertiesAnnotation(DexTargetPackage targetPackage) { // Find property accessors var propertyMap = new Dictionary <PropertyDefinition, MethodBuilder[]>(); foreach (var methodBuilder in methodBuilders) { PropertyDefinition propertyDef; bool isSetter; if (!methodBuilder.IsPropertyAccessor(out propertyDef, out isSetter)) { continue; } MethodBuilder[] accessors; if (!propertyMap.TryGetValue(propertyDef, out accessors)) { accessors = new MethodBuilder[2]; propertyMap[propertyDef] = accessors; } accessors[isSetter ? 1 : 0] = methodBuilder; } // Build annotations if (propertyMap.Count > 0) { var propertyClass = compiler.GetDot42InternalType("IProperty").GetClassReference(targetPackage); var propertiesClass = compiler.GetDot42InternalType("IProperties").GetClassReference(targetPackage); var propertyAnnotations = new List <Annotation>(); foreach (var pair in propertyMap) { var provider = new PropertyAnnotationProvider { Annotations = new List <Annotation>() }; AttributeAnnotationInstanceBuilder.CreateAttributeAnnotations(compiler, pair.Key, provider, targetPackage, true); string propName = pair.Key.Name; var ann = new Annotation(propertyClass, AnnotationVisibility.Runtime, new AnnotationArgument("Name", propName)); if (pair.Value[0] != null) { var getter = pair.Value[0].DexMethod; if (getter.Prototype.Parameters.Count > 0) { // When the VS plugin correctly supports DLog.Info, // this should be changed to Info again. DLog.Debug(DContext.CompilerCodeGenerator, "not generating property for getter with arguments " + getter); continue; } var getterName = getter.Name; if (getterName != "get_" + propName) { ann.Arguments.Add(new AnnotationArgument("Get", getterName)); } } if (pair.Value[1] != null) { var setter = pair.Value[1].DexMethod; if (setter.Prototype.Parameters.Count != 1) { DLog.Info(DContext.CompilerCodeGenerator, "not generating property for setter with wrong argument count " + setter); continue; } var setterName = setter.Name; if (setterName != "set_" + propName) { ann.Arguments.Add(new AnnotationArgument("Set", setterName)); } } //propType = pair.Key.PropertyType; // Mono.Cecil.TypeReference propType = null; var attributes = provider.Annotations.FirstOrDefault(); if (attributes != null && attributes.Arguments[0].Value != null) { ann.Arguments.Add(new AnnotationArgument("Attributes", attributes.Arguments[0].Value)); } propertyAnnotations.Add(ann); } var propAnn = new Annotation(propertiesClass, AnnotationVisibility.Runtime, new AnnotationArgument("Properties", propertyAnnotations.ToArray())); Class.Annotations.Add(propAnn); } }
/// <summary> /// /// </summary> public int SetNextStatement(IDebugStackFrame2 pStackFrame, IDebugCodeContext2 pCodeContext) { // TODO: move this code to DalvikThread, or to a SetNextInstructionManager DLog.Debug(DContext.VSDebuggerComCall, "IDebugThread2.SetNextStatement"); var stack = (DebugStackFrame)pStackFrame; var ctx = (DebugCodeContext)pCodeContext; // nothing to do. if (ctx.Location.Equals(stack.Location)) { return(VSConstants.S_OK); } if (!ctx.Location.IsSameMethod(stack.Location)) { return(HResults.E_CANNOT_SETIP_TO_DIFFERENT_FUNCTION); } var loc = stack.GetDocumentLocationAsync().Await(DalvikProcess.VmTimeout); if (loc.MethodEntry == null) { DLog.Info(DContext.VSStatusBar, "Can not set next instruction: Debug info not available."); return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } var nextInstrVar = loc.MethodEntry.Variables.FirstOrDefault(v => v.Name == DebuggerConstants.SetNextInstructionVariableName); if (nextInstrVar == null) { DLog.Info(DContext.VSStatusBar, "Can not set next instruction: missing compiler setting or method optimized."); return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } // make sure there are no branch instructions // between the current instruction and our branch instruction. // note that for convinence, we *do* allow assignments to // fields of objects, even though these are visible to the // program. var disassembly = Program.DisassemblyProvider.GetFromLocation(loc); if (disassembly == null) { return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } var body = disassembly.Method.Body; int idx = body.Instructions.FindIndex(i => (ulong)i.Offset == loc.Location.Index); if (idx == -1) { return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } bool foundSetNextInstruction = false; for (; idx < body.Instructions.Count; ++idx) { var ins = body.Instructions[idx]; foundSetNextInstruction = ins.OpCode == OpCodes.If_nez && ins.Registers.Count == 1 && ins.Registers[0].Index == nextInstrVar.Register; if (foundSetNextInstruction) { break; } if (ins.OpCode.IsJump()) { break; } } if (!foundSetNextInstruction) { DLog.Info(DContext.VSStatusBar, "Can not set next instruction from current position. Try again at a later position if any."); return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } DLog.Info(DContext.VSStatusBar, "Setting next instruction to beginning of block."); // find target instruction. var targetIns = (Instruction)body.Instructions[idx].Operand; idx = body.Instructions.FindIndex(p => p.Offset == targetIns.Offset); idx = FindNextLocationWithSource(disassembly, idx) ?? idx; targetIns = body.Instructions[idx]; var targetLoc = loc.Location.GetAtIndex(targetIns.Offset); // set a temporary breakpoint. The reset logic could get into a "DalvikTemporaryBreakpoint" class. var bp = new DalvikAwaitableBreakpoint(targetLoc); var waitBp = bp.WaitUntilHit(); var waitBound = Debugger.Process.BreakpointManager.SetBreakpoint(bp); try { if (!waitBound.Await(DalvikProcess.VmTimeout)) { return(HResults.E_CANNOT_SET_NEXT_STATEMENT_GENERAL); } // set the special variable. var newSlotVal = new SlotValue(nextInstrVar.Register, Jdwp.Tag.Int, 1); Debugger.StackFrame.SetValuesAsync(stack.Thread.Id, stack.Id, newSlotVal) .Await(DalvikProcess.VmTimeout); // resume the process. Debugger.Process.ResumeAsync(); // wait for breakpoint to be hit. try { waitBp.Await(1000); } catch (Exception) { // ups. something went wrong. suspend again. if (!Debugger.Process.IsSuspended) { Debugger.Process.SuspendAsync(); } return(VSConstants.E_FAIL); } return(VSConstants.S_OK); } finally { // clear the breakpoint again. Debugger.Process.BreakpointManager.ResetAsync(bp) .Await(DalvikProcess.VmTimeout); // reset the special variable, in case this was not performed automatically. // (should not happen, but maybe the set value code got optimized away per // accident) var newSlotVal = new SlotValue(nextInstrVar.Register, Jdwp.Tag.Int, 0); Debugger.StackFrame.SetValuesAsync(stack.Thread.Id, stack.Id, newSlotVal) .Await(DalvikProcess.VmTimeout); } }