示例#1
0
        internal void InitializeThreads(Inferior inferior)
        {
            TargetAddress ptr = inferior.ReadAddress(MonoDebuggerInfo.ThreadTable);

            while (!ptr.IsNull)
            {
                int size;
                if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3))
                {
                    size = 60 + inferior.TargetMemoryInfo.TargetAddressSize;
                }
                else
                {
                    size = 32 + inferior.TargetMemoryInfo.TargetAddressSize;
                }
                TargetReader reader = new TargetReader(inferior.ReadMemory(ptr, size));

                long          tid       = reader.ReadLongInteger();
                TargetAddress lmf_addr  = reader.ReadAddress();
                TargetAddress end_stack = reader.ReadAddress();

                TargetAddress extended_notifications_addr = ptr + 24;

                if (inferior.TargetMemoryInfo.TargetAddressSize == 4)
                {
                    tid &= 0x00000000ffffffffL;
                }

                reader.Offset += 8;
                ptr            = reader.ReadAddress();

                ThreadFlags flags = ThreadFlags.None;
                if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3))
                {
                    reader.Offset = 56 + inferior.TargetAddressSize;
                    flags         = (ThreadFlags)reader.ReadInteger();
                }

                bool found = false;
                foreach (SingleSteppingEngine engine in process.Engines)
                {
                    if (engine.TID != tid)
                    {
                        continue;
                    }

                    engine.SetManagedThreadData(lmf_addr, extended_notifications_addr);
                    engine.OnManagedThreadCreated(end_stack);
                    check_thread_flags(engine, flags);
                    found = true;
                    break;
                }

                if (!found)
                {
                    Report.Error("Cannot find thread {0:x} in {1}",
                                 tid, process.ProcessStart.CommandLine);
                }
            }
        }
示例#2
0
        protected void initialize_notifications(Inferior inferior)
        {
            TargetAddress executable_code_buffer = inferior.ReadAddress(
                debugger_info.ExecutableCodeBuffer);

            HasCodeBuffer = !executable_code_buffer.IsNull;

            mono_runtime_info = mono_debugger_server_initialize_mono_runtime(
                inferior.TargetAddressSize,
                debugger_info.NotificationAddress.Address,
                executable_code_buffer.Address,
                debugger_info.ExecutableCodeBufferSize,
                debugger_info.BreakpointInfo.Address,
                debugger_info.BreakpointInfoIndex.Address,
                debugger_info.BreakpointArraySize);
            inferior.SetRuntimeInfo(mono_runtime_info);

            debugger_version = inferior.ReadInteger(debugger_info.DebuggerVersion);

            if (notification_bpt != null)
            {
                notification_bpt.Remove(inferior);
                notification_bpt = null;
            }

            if (debugger_info.HasThreadAbortSignal)
            {
                thread_abort_signal = inferior.ReadInteger(debugger_info.ThreadAbortSignal);
            }
            else
            {
                thread_abort_signal = inferior.MonoThreadAbortSignal;
            }
        }
        void check_for_mono_runtime(Inferior inferior, Bfd bfd)
        {
            TargetAddress info = bfd.GetSectionAddress(".mdb_debug_info");

            if (info.IsNull)
            {
                return;
            }

            TargetAddress data = inferior.ReadAddress(info);

            if (data.IsNull)
            {
                //
                // See CheckForPendingMonoInit() below - this should only happen when
                // the Mono runtime is embedded - for instance Moonlight inside Firefox.
                //
                // Note that we have to do a symbol lookup for it because we do not know
                // whether the mono runtime is recent enough to have this variable.
                //
                data = bfd.LookupSymbol("MONO_DEBUGGER__using_debugger");
                if (data.IsNull)
                {
                    Report.Error("Failed to initialize the Mono runtime!");
                    return;
                }

                inferior.WriteInteger(data, 1);
                pending_mono_init = info;
                return;
            }

            Process.InitializeMono(inferior, data);
        }
        void check_nptl_setxid(Inferior inferior, Bfd bfd)
        {
            if (setxid_breakpoint != null)
            {
                return;
            }

            TargetAddress vtable = bfd.LookupSymbol("__libc_pthread_functions");

            if (vtable.IsNull)
            {
                return;
            }

            /*
             * Big big hack to allow debugging gnome-vfs:
             * We intercept any calls to __nptl_setxid() and make it
             * return 0.  This is safe to do since we do not allow
             * debugging setuid programs or running as root, so setxid()
             * will always be a no-op anyways.
             */

            TargetAddress nptl_setxid = inferior.ReadAddress(vtable + 51 * inferior.TargetAddressSize);

            if (!nptl_setxid.IsNull)
            {
                setxid_breakpoint = new SetXidBreakpoint(this, nptl_setxid);
                setxid_breakpoint.Insert(inferior);
            }
        }
示例#5
0
        void check_for_mono_runtime(Inferior inferior, Bfd bfd)
        {
            TargetAddress info = bfd.LookupSymbol("MONO_DEBUGGER__debugger_info_ptr");

            if (info.IsNull)
            {
                return;
            }

            TargetAddress data = inferior.ReadAddress(info);

            if (data.IsNull)
            {
                //
                // See CheckForPendingMonoInit() below - this should only happen when
                // the Mono runtime is embedded - for instance Moonlight inside Firefox.
                //
                // Note that we have to do a symbol lookup for it because we do not know
                // whether the mono runtime is recent enough to have this variable.
                //
                data = bfd.LookupSymbol("MONO_DEBUGGER__using_debugger");
                if (data.IsNull)
                {
                    Report.Error("Failed to initialize the Mono runtime!");
                    return;
                }

                inferior.WriteInteger(data, 1);
                pending_mono_init = info;

                // Add a breakpoint in mini_debugger_init, to make sure that InitializeMono()
                // gets called in time to set the breakpoint at debugger_initialize, needed to
                // initialize the notifications.
                TargetAddress mini_debugger_init = bfd.LookupSymbol("mini_debugger_init");
                if (!mini_debugger_init.IsNull)
                {
                    Instruction insn = inferior.Architecture.ReadInstruction(inferior, mini_debugger_init);
                    if ((insn == null) || !insn.CanInterpretInstruction)
                    {
                        throw new InternalError("Unknown dynlink breakpoint: {0}", mini_debugger_init);
                    }

                    DynlinkBreakpoint init_breakpoint = new DynlinkBreakpoint(this, insn);
                    init_breakpoint.Insert(inferior);
                }
                return;
            }

            Process.InitializeMono(inferior, data);
        }
        internal override void Hack_ReturnNull(Inferior inferior)
        {
            Registers     regs = inferior.GetRegisters();
            TargetAddress rsp  = new TargetAddress(
                inferior.AddressDomain, regs [(int)X86_Register.RSP].GetValue());
            TargetAddress rip = inferior.ReadAddress(rsp);

            rsp += TargetAddressSize;

            regs [(int)X86_Register.RIP].SetValue(rip);
            regs [(int)X86_Register.RSP].SetValue(rsp);
            regs [(int)X86_Register.RAX].SetValue(TargetAddress.Null);

            inferior.SetRegisters(regs);
        }
示例#7
0
        internal override bool CheckForPendingMonoInit(Inferior inferior)
        {
            if (pending_mono_init.IsNull)
            {
                return(false);
            }

            TargetAddress data = inferior.ReadAddress(pending_mono_init);

            if (data.IsNull)
            {
                return(false);
            }

            pending_mono_init = TargetAddress.Null;
            Process.InitializeMono(inferior, data);
            return(true);
        }
示例#8
0
        protected void initialize_notifications(Inferior inferior)
        {
            TargetAddress executable_code_buffer = inferior.ReadAddress (
                debugger_info.ExecutableCodeBuffer);
            HasCodeBuffer = !executable_code_buffer.IsNull;

            mono_runtime_info = mono_debugger_server_initialize_mono_runtime (
                inferior.TargetAddressSize,
                debugger_info.NotificationAddress.Address,
                executable_code_buffer.Address,
                debugger_info.ExecutableCodeBufferSize,
                debugger_info.BreakpointInfo.Address,
                debugger_info.BreakpointInfoIndex.Address,
                debugger_info.BreakpointArraySize);
            inferior.SetRuntimeInfo (mono_runtime_info);

            debugger_version = inferior.ReadInteger (debugger_info.DebuggerVersion);

            if (notification_bpt != null) {
                notification_bpt.Remove (inferior);
                notification_bpt = null;
            }

            if (debugger_info.HasThreadAbortSignal)
                thread_abort_signal = inferior.ReadInteger (debugger_info.ThreadAbortSignal);
            else
                thread_abort_signal = inferior.MonoThreadAbortSignal;
        }
示例#9
0
        internal void InitializeThreads(Inferior inferior)
        {
            TargetAddress ptr = inferior.ReadAddress (MonoDebuggerInfo.ThreadTable);
            while (!ptr.IsNull) {
                int size;
                if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3))
                    size = 60 + inferior.TargetMemoryInfo.TargetAddressSize;
                else
                    size = 32 + inferior.TargetMemoryInfo.TargetAddressSize;
                TargetReader reader = new TargetReader (inferior.ReadMemory (ptr, size));

                long tid = reader.ReadLongInteger ();
                TargetAddress lmf_addr = reader.ReadAddress ();
                TargetAddress end_stack = reader.ReadAddress ();

                TargetAddress extended_notifications_addr = ptr + 24;

                if (inferior.TargetMemoryInfo.TargetAddressSize == 4)
                    tid &= 0x00000000ffffffffL;

                reader.Offset += 8;
                ptr = reader.ReadAddress ();

                ThreadFlags flags = ThreadFlags.None;
                if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) {
                    reader.Offset = 56 + inferior.TargetAddressSize;
                    flags = (ThreadFlags) reader.ReadInteger ();
                }

                bool found = false;
                foreach (SingleSteppingEngine engine in process.Engines) {
                    if (engine.TID != tid)
                        continue;

                    engine.SetManagedThreadData (lmf_addr, extended_notifications_addr);
                    engine.OnManagedThreadCreated (end_stack);
                    check_thread_flags (engine, flags);
                    found = true;
                    break;
                }

                if (!found)
                    Report.Error ("Cannot find thread {0:x} in {1}",
                              tid, process.ProcessStart.CommandLine);
            }
        }
示例#10
0
        internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior,
						ref Inferior.ChildEvent cevent, out bool resume_target)
        {
            if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION) {
                NotificationType type = (NotificationType) cevent.Argument;

                Report.Debug (DebugFlags.EventLoop,
                          "{0} received notification {1}: {2}",
                          engine, type, cevent);

                switch (type) {
                case NotificationType.AcquireGlobalThreadLock:
                    Report.Debug (DebugFlags.Threads,
                              "{0} received notification {1}", engine, type);
                    engine.Process.AcquireGlobalThreadLock (engine);
                    break;

                case NotificationType.ReleaseGlobalThreadLock:
                    Report.Debug (DebugFlags.Threads,
                              "{0} received notification {1}", engine, type);
                    engine.Process.ReleaseGlobalThreadLock (engine);
                    break;

                case NotificationType.ThreadCreated: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data2);

                    TargetAddress lmf = inferior.ReadAddress (data + 8);
                    engine.SetManagedThreadData (lmf, data + 24);

                    if (MonoDebuggerInfo.CheckRuntimeVersion (81, 3)) {
                        int flags_offset = 56 + inferior.TargetAddressSize;
                        ThreadFlags flags = (ThreadFlags) inferior.ReadInteger (data + flags_offset);
                        check_thread_flags (engine, flags);
                    }

                    Report.Debug (DebugFlags.Threads,
                              "{0} managed thread created: {1:x} {2} {3} - {4}",
                              engine, cevent.Data1, data, lmf, engine.LMFAddress);
                    break;
                }

                case NotificationType.ThreadCleanup: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);

                    Report.Debug (DebugFlags.Threads,
                              "{0} managed thread cleanup: {1:x} {2}",
                              engine, cevent.Data2, data);
                    break;
                }

                case NotificationType.GcThreadCreated: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);
                    long tid = cevent.Data2;

                    Report.Debug (DebugFlags.Threads,
                              "{0} created gc thread: {1:x} {2}",
                              engine, tid, data);

                    engine = engine.Process.GetEngineByTID (inferior, tid);
                    if (engine == null)
                        throw new InternalError ();

                    engine.OnManagedThreadCreated (data);
                    break;
                }

                case NotificationType.GcThreadExited:
                    Report.Debug (DebugFlags.Threads, "{0} gc thread exited", engine);
                    engine.OnManagedThreadExited ();
                    try {
                        inferior.Continue ();
                    } catch {
                        // Ignore errors; for some reason, the thread may have died
                        // already by the time get this notification.
                    }
                    resume_target = false;
                    return true;

                case NotificationType.InitializeThreadManager:
                    csharp_language = inferior.Process.CreateMonoLanguage (
                        debugger_info);
                    if (engine.Process.IsAttached)
                        csharp_language.InitializeAttach (inferior);
                    else
                        csharp_language.Initialize (inferior);

                    break;

                case NotificationType.ReachedMain: {
                    Inferior.StackFrame iframe = inferior.GetCurrentFrame (false);
                    engine.SetMainReturnAddress (iframe.StackPointer);
                    engine.Process.OnProcessReachedMainEvent ();
                    resume_target = !engine.InitializeBreakpoints ();
                    return true;
                }

                case NotificationType.WrapperMain:
                    break;
                case NotificationType.MainExited:
                    engine.SetMainReturnAddress (TargetAddress.Null);
                    break;

                case NotificationType.UnhandledException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.UNHANDLED_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.HandleException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.HANDLE_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.ThrowException:
                    cevent = new Inferior.ChildEvent (
                        Inferior.ChildEventType.THROW_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return false;

                case NotificationType.FinalizeManagedCode:
                    mono_debugger_server_finalize_mono_runtime (mono_runtime_info);
                    mono_runtime_info = IntPtr.Zero;
                    csharp_language = null;
                    break;

                case NotificationType.OldTrampoline:
                case NotificationType.Trampoline:
                    resume_target = false;
                    return false;

                case NotificationType.ClassInitialized:
                    break;

                case NotificationType.InterruptionRequest:
                    inferior.WriteInteger (MonoDebuggerInfo.InterruptionRequest, 0);
                    var callbacks = managed_callbacks;
                    managed_callbacks = new Queue<ManagedCallbackData> ();
                    resume_target = !engine.OnManagedCallback (callbacks);
                    return true;

                default: {
                    TargetAddress data = new TargetAddress (
                        inferior.AddressDomain, cevent.Data1);

                    resume_target = csharp_language.Notification (
                        engine, inferior, type, data, cevent.Data2);
                    return true;
                }
                }

                resume_target = true;
                return true;
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) &&
                (cevent.Argument == thread_abort_signal)) {
                resume_target = true;
                return true;
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument != 0) && !
                engine.Process.Session.Config.StopOnManagedSignals) {
                if (inferior.IsManagedSignal ((int) cevent.Argument)) {
                    resume_target = true;
                    return true;
                }
            }

            resume_target = false;
            return false;
        }
示例#11
0
        public override bool InterpretInstruction(Inferior inferior)
        {
            switch (InstructionType)
            {
            case Type.IndirectJump:
            case Type.Jump: {
                TargetAddress target = GetEffectiveAddress(inferior);
                Registers     regs   = inferior.GetRegisters();
                regs [(int)X86_Register.RIP].SetValue(target);
                inferior.SetRegisters(regs);
                return(true);
            }

            case Type.IndirectCall:
            case Type.Call: {
                TargetAddress target = GetEffectiveAddress(inferior);
                Registers     regs   = inferior.GetRegisters();

                TargetAddress rip = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RIP].Value);
                TargetAddress rsp = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RSP].Value);

                inferior.WriteAddress(rsp - 8, rip + InstructionSize);

                regs [(int)X86_Register.RSP].SetValue(rsp - 8);
                regs [(int)X86_Register.RIP].SetValue(target);
                inferior.SetRegisters(regs);
                return(true);
            }

            case Type.Ret: {
                Registers regs = inferior.GetRegisters();

                TargetAddress rsp = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RSP].Value);

                TargetAddress rip = inferior.ReadAddress(rsp);
                rsp += 8 + Displacement;

                regs [(int)X86_Register.RSP].SetValue(rsp);
                regs [(int)X86_Register.RIP].SetValue(rip);
                inferior.SetRegisters(regs);
                return(true);
            }

            case Type.Interpretable: {
                Registers regs = inferior.GetRegisters();

                TargetAddress rsp = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RSP].Value);
                TargetAddress rbp = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RBP].Value);
                TargetAddress rip = new TargetAddress(
                    inferior.AddressDomain, regs [(int)X86_Register.RIP].Value);

                if (Code [0] == 0x55)                 /* push %rbp */
                {
                    inferior.WriteAddress(rsp - 8, rbp);
                    regs [(int)X86_Register.RSP].SetValue(rsp - 8);
                    regs [(int)X86_Register.RIP].SetValue(rip + 1);
                    inferior.SetRegisters(regs);
                    return(true);
                }

                return(false);
            }

            default:
                return(false);
            }
        }
示例#12
0
        internal bool HandleChildEvent(SingleSteppingEngine engine, Inferior inferior,
                                       ref Inferior.ChildEvent cevent, out bool resume_target)
        {
            if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION)
            {
                NotificationType type = (NotificationType)cevent.Argument;

                Report.Debug(DebugFlags.EventLoop,
                             "{0} received notification {1}: {2}",
                             engine, type, cevent);

                switch (type)
                {
                case NotificationType.AcquireGlobalThreadLock:
                    Report.Debug(DebugFlags.Threads,
                                 "{0} received notification {1}", engine, type);
                    engine.Process.AcquireGlobalThreadLock(engine);
                    break;

                case NotificationType.ReleaseGlobalThreadLock:
                    Report.Debug(DebugFlags.Threads,
                                 "{0} received notification {1}", engine, type);
                    engine.Process.ReleaseGlobalThreadLock(engine);
                    break;

                case NotificationType.ThreadCreated: {
                    TargetAddress data = new TargetAddress(
                        inferior.AddressDomain, cevent.Data2);

                    TargetAddress lmf = inferior.ReadAddress(data + 8);
                    engine.SetManagedThreadData(lmf, data + 24);

                    if (MonoDebuggerInfo.CheckRuntimeVersion(81, 3))
                    {
                        int         flags_offset = 56 + inferior.TargetAddressSize;
                        ThreadFlags flags        = (ThreadFlags)inferior.ReadInteger(data + flags_offset);
                        check_thread_flags(engine, flags);
                    }

                    Report.Debug(DebugFlags.Threads,
                                 "{0} managed thread created: {1:x} {2} {3} - {4}",
                                 engine, cevent.Data1, data, lmf, engine.LMFAddress);
                    break;
                }

                case NotificationType.ThreadCleanup: {
                    TargetAddress data = new TargetAddress(
                        inferior.AddressDomain, cevent.Data1);

                    Report.Debug(DebugFlags.Threads,
                                 "{0} managed thread cleanup: {1:x} {2}",
                                 engine, cevent.Data2, data);
                    break;
                }

                case NotificationType.GcThreadCreated: {
                    TargetAddress data = new TargetAddress(
                        inferior.AddressDomain, cevent.Data1);
                    long tid = cevent.Data2;

                    Report.Debug(DebugFlags.Threads,
                                 "{0} created gc thread: {1:x} {2}",
                                 engine, tid, data);

                    engine = engine.Process.GetEngineByTID(inferior, tid);
                    if (engine == null)
                    {
                        throw new InternalError();
                    }

                    engine.OnManagedThreadCreated(data);
                    break;
                }

                case NotificationType.GcThreadExited:
                    Report.Debug(DebugFlags.Threads, "{0} gc thread exited", engine);
                    engine.OnManagedThreadExited();
                    try {
                        inferior.Continue();
                    } catch {
                        // Ignore errors; for some reason, the thread may have died
                        // already by the time get this notification.
                    }
                    resume_target = false;
                    return(true);

                case NotificationType.InitializeThreadManager:
                    csharp_language = inferior.Process.CreateMonoLanguage(
                        debugger_info);
                    if (engine.Process.IsAttached)
                    {
                        csharp_language.InitializeAttach(inferior);
                    }
                    else
                    {
                        csharp_language.Initialize(inferior);
                    }

                    break;

                case NotificationType.ReachedMain: {
                    Inferior.StackFrame iframe = inferior.GetCurrentFrame(false);
                    engine.SetMainReturnAddress(iframe.StackPointer);
                    engine.Process.OnProcessReachedMainEvent();
                    resume_target = !engine.InitializeBreakpoints();
                    return(true);
                }

                case NotificationType.WrapperMain:
                    break;

                case NotificationType.MainExited:
                    engine.SetMainReturnAddress(TargetAddress.Null);
                    break;

                case NotificationType.UnhandledException:
                    cevent = new Inferior.ChildEvent(
                        Inferior.ChildEventType.UNHANDLED_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return(false);

                case NotificationType.HandleException:
                    cevent = new Inferior.ChildEvent(
                        Inferior.ChildEventType.HANDLE_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return(false);

                case NotificationType.ThrowException:
                    cevent = new Inferior.ChildEvent(
                        Inferior.ChildEventType.THROW_EXCEPTION,
                        0, cevent.Data1, cevent.Data2);
                    resume_target = false;
                    return(false);

                case NotificationType.FinalizeManagedCode:
                    mono_debugger_server_finalize_mono_runtime(mono_runtime_info);
                    mono_runtime_info = IntPtr.Zero;
                    csharp_language   = null;
                    break;

                case NotificationType.OldTrampoline:
                case NotificationType.Trampoline:
                    resume_target = false;
                    return(false);

                case NotificationType.ClassInitialized:
                    break;

                case NotificationType.InterruptionRequest:
                    inferior.WriteInteger(MonoDebuggerInfo.InterruptionRequest, 0);
                    var callbacks = managed_callbacks;
                    managed_callbacks = new Queue <ManagedCallbackData> ();
                    resume_target     = !engine.OnManagedCallback(callbacks);
                    return(true);

                default: {
                    TargetAddress data = new TargetAddress(
                        inferior.AddressDomain, cevent.Data1);

                    resume_target = csharp_language.Notification(
                        engine, inferior, type, data, cevent.Data2);
                    return(true);
                }
                }

                resume_target = true;
                return(true);
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) &&
                (cevent.Argument == thread_abort_signal))
            {
                resume_target = true;
                return(true);
            }

            if ((cevent.Type == Inferior.ChildEventType.CHILD_STOPPED) && (cevent.Argument != 0) && !
                engine.Process.Session.Config.StopOnManagedSignals)
            {
                if (inferior.IsManagedSignal((int)cevent.Argument))
                {
                    resume_target = true;
                    return(true);
                }
            }

            resume_target = false;
            return(false);
        }