public void PrintStatistics()
 {
     if (IsEnabled)
     {
         DLog.Info(DContext.CompilerCodeGenerator, "Compiler cache: {0} hits and {1} misses.", statCacheHits, statCacheMisses);
     }
 }
Example #2
0
            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);
            }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
            }
        }
Example #5
0
        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);
            }
        }
Example #6
0
        /// <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);
            }
        }