<rdar://problem/12649160>
Added the ability to debug through your process exec'ing itself to the same architecture.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@169340 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 0f43040..5455a24 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -5111,3 +5111,22 @@
{
m_thread_list.Flush();
}
+
+void
+Process::DidExec ()
+{
+ Target &target = GetTarget();
+ target.CleanupProcess ();
+ ModuleList unloaded_modules (target.GetImages());
+ target.ModulesDidUnload (unloaded_modules);
+ target.GetSectionLoadList().Clear();
+ m_dynamic_checkers_ap.reset();
+ m_abi_sp.reset();
+ m_os_ap.reset();
+ m_dyld_ap.reset();
+ m_image_tokens.clear();
+ m_allocated_memory_cache.Clear();
+ m_language_runtimes.clear();
+ DoDidExec();
+ CompleteAttach ();
+}
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 082fddd..0a45d33 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -147,6 +147,7 @@
{
case eStopReasonWatchpoint:
case eStopReasonException:
+ case eStopReasonExec:
case eStopReasonSignal:
// In all these cases we want to stop in the deepest most frame.
m_current_inlined_pc = curr_pc;
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index bae1e4a..de76748 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -862,6 +862,49 @@
ThreadPlanSP m_plan_sp;
ValueObjectSP m_return_valobj_sp;
};
+
+class StopInfoExec : public StopInfo
+{
+public:
+
+ StopInfoExec (Thread &thread) :
+ StopInfo (thread, LLDB_INVALID_UID),
+ m_performed_action (false)
+ {
+ }
+
+ virtual
+ ~StopInfoExec ()
+ {
+ }
+
+ virtual StopReason
+ GetStopReason () const
+ {
+ return eStopReasonExec;
+ }
+
+ virtual const char *
+ GetDescription ()
+ {
+ return "exec";
+ }
+protected:
+protected:
+
+ virtual void
+ PerformAction (Event *event_ptr)
+ {
+ // Only perform the action once
+ if (m_performed_action)
+ return;
+ m_performed_action = true;
+ m_thread.GetProcess()->DidExec();
+ }
+
+ bool m_performed_action;
+};
+
} // namespace lldb_private
StopInfoSP
@@ -906,6 +949,12 @@
return StopInfoSP (new StopInfoException (thread, description));
}
+StopInfoSP
+StopInfo::CreateStopReasonWithExec (Thread &thread)
+{
+ return StopInfoSP (new StopInfoExec (thread));
+}
+
ValueObjectSP
StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
{
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 77daef6..433ddd0 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -130,6 +130,21 @@
}
void
+Target::CleanupProcess ()
+{
+ // Do any cleanup of the target we need to do between process instances.
+ // NB It is better to do this before destroying the process in case the
+ // clean up needs some help from the process.
+ m_breakpoint_list.ClearAllBreakpointSites();
+ m_internal_breakpoint_list.ClearAllBreakpointSites();
+ // Disable watchpoints just on the debugger side.
+ Mutex::Locker locker;
+ this->GetWatchpointList().GetListMutex(locker);
+ DisableAllWatchpoints(false);
+ ClearAllWatchpointHitCounts();
+}
+
+void
Target::DeleteCurrentProcess ()
{
if (m_process_sp.get())
@@ -140,16 +155,8 @@
m_process_sp->Finalize();
- // Do any cleanup of the target we need to do between process instances.
- // NB It is better to do this before destroying the process in case the
- // clean up needs some help from the process.
- m_breakpoint_list.ClearAllBreakpointSites();
- m_internal_breakpoint_list.ClearAllBreakpointSites();
- // Disable watchpoints just on the debugger side.
- Mutex::Locker locker;
- this->GetWatchpointList().GetListMutex(locker);
- DisableAllWatchpoints(false);
- ClearAllWatchpointHitCounts();
+ CleanupProcess ();
+
m_process_sp.reset();
}
}
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 4c6995c..7a5aafb 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -1574,6 +1574,7 @@
case eStopReasonWatchpoint: return "watchpoint";
case eStopReasonSignal: return "signal";
case eStopReasonException: return "exception";
+ case eStopReasonExec: return "exec";
case eStopReasonPlanComplete: return "plan complete";
}
diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp
index f8e4b6a..ebf4686 100644
--- a/source/Target/ThreadPlanBase.cpp
+++ b/source/Target/ThreadPlanBase.cpp
@@ -139,6 +139,14 @@
m_thread.DiscardThreadPlans(false);
return true;
+ case eStopReasonExec:
+ // If we crashed, discard thread plans and stop. Don't force the discard, however,
+ // since on rerun the target may clean up this exception and continue normally from there.
+ if (log)
+ log->Printf("Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 " (exec.)", m_thread.GetID());
+ m_thread.DiscardThreadPlans(false);
+ return true;
+
case eStopReasonSignal:
if (stop_info_sp->ShouldStop(event_ptr))
{
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index ca24172..f4339a4 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -335,6 +335,7 @@
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
+ case eStopReasonExec:
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index 540539e..5343324 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -251,6 +251,7 @@
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
+ case eStopReasonExec:
return false;
default:
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index ba21eda..66754d2 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -319,6 +319,7 @@
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
+ case eStopReasonExec:
default:
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
index 1e454e7..95b0a35 100644
--- a/source/Target/ThreadPlanStepUntil.cpp
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -291,6 +291,7 @@
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
+ case eStopReasonExec:
m_explains_stop = false;
break;
default: