summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Target
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target')
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp13
-rw-r--r--contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Platform.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Process.cpp558
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Queue.cpp127
-rw-r--r--contrib/llvm/tools/lldb/source/Target/QueueItem.cpp77
-rw-r--r--contrib/llvm/tools/lldb/source/Target/QueueList.cpp102
-rw-r--r--contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp182
-rw-r--r--contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp19
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StopInfo.cpp15
-rw-r--r--contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Target.cpp264
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Thread.cpp135
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadList.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Target/UnwindAssembly.cpp6
18 files changed, 1396 insertions, 208 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
index 7a8b601..db4025f 100644
--- a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
@@ -154,7 +154,7 @@ ExecutionContext::ExecutionContext (const ExecutionContextRef &exe_ctx_ref) :
{
}
-ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr) :
+ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr, bool thread_and_frame_only_if_stopped) :
m_target_sp (),
m_process_sp (),
m_thread_sp (),
@@ -164,8 +164,11 @@ ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr)
{
m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
- m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
- m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+ if (!thread_and_frame_only_if_stopped || (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true)))
+ {
+ m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
+ m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+ }
}
}
@@ -824,9 +827,9 @@ ExecutionContextRef::GetFrameSP () const
}
ExecutionContext
-ExecutionContextRef::Lock () const
+ExecutionContextRef::Lock (bool thread_and_frame_only_if_stopped) const
{
- return ExecutionContext(this);
+ return ExecutionContext(this, thread_and_frame_only_if_stopped);
}
diff --git a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
index 2fdc253..a2b7f1d 100644
--- a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
@@ -269,7 +269,8 @@ LanguageRuntime::CreateExceptionBreakpoint (Target &target,
BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language));
bool hardware = false;
- BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware));
+ bool resolve_indirect_functions = false;
+ BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions));
if (is_internal)
exc_breakpt_sp->SetBreakpointKind("exception");
diff --git a/contrib/llvm/tools/lldb/source/Target/Platform.cpp b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
index 66f9c0e..d6010fb 100644
--- a/contrib/llvm/tools/lldb/source/Target/Platform.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
@@ -81,9 +81,9 @@ Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
}
Error
-Platform::GetFile (const FileSpec &platform_file,
- const UUID *uuid_ptr,
- FileSpec &local_file)
+Platform::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
{
// Default to the local case
local_file = platform_file;
@@ -255,7 +255,9 @@ Platform::Platform (bool is_host) :
m_rsync_prefix (),
m_supports_ssh (false),
m_ssh_opts (),
- m_ignores_remote_hostname (false)
+ m_ignores_remote_hostname (false),
+ m_trap_handlers(),
+ m_calculated_trap_handlers (false)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@@ -1039,6 +1041,8 @@ Platform::DebugProcess (ProcessLaunchInfo &launch_info,
process_sp = Attach (attach_info, debugger, target, listener, error);
if (process_sp)
{
+ launch_info.SetHijackListener(attach_info.GetHijackListener());
+
// Since we attached to the process, it will think it needs to detach
// if the process object just goes away without an explicit call to
// Process::Kill() or Process::Detach(), so let it know to kill the
@@ -1388,3 +1392,15 @@ Platform::GetEnvironment (StringList &environment)
environment.Clear();
return false;
}
+
+const std::vector<ConstString> &
+Platform::GetTrapHandlerSymbolNames ()
+{
+ if (!m_calculated_trap_handlers)
+ {
+ CalculateTrapHandlerSymbolNames();
+ m_calculated_trap_handlers = true;
+ }
+ return m_trap_handlers;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Target/Process.cpp b/contrib/llvm/tools/lldb/source/Target/Process.cpp
index 1de322a..1256ad3 100644
--- a/contrib/llvm/tools/lldb/source/Target/Process.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Process.cpp
@@ -18,14 +18,16 @@
#include "lldb/Core/Event.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Terminal.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/OperatingSystem.h"
@@ -41,6 +43,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#ifndef LLDB_DISABLE_POSIX
#include <spawn.h>
@@ -1025,6 +1028,8 @@ Process::Process(Target &target, Listener &listener) :
m_thread_list (this),
m_extended_thread_list (this),
m_extended_thread_stop_id (0),
+ m_queue_list (this),
+ m_queue_list_stop_id (0),
m_notifications (),
m_image_tokens (),
m_listener (listener),
@@ -1048,6 +1053,7 @@ Process::Process(Target &target, Listener &listener) :
m_currently_handling_event(false),
m_finalize_called(false),
m_clear_thread_plans_on_stop (false),
+ m_force_next_event_delivery(false),
m_last_broadcast_state (eStateInvalid),
m_destroy_in_process (false),
m_can_jit(eCanJITDontKnow)
@@ -1151,6 +1157,8 @@ Process::Finalize()
m_thread_list_real.Destroy();
m_thread_list.Destroy();
m_extended_thread_list.Destroy();
+ m_queue_list.Clear();
+ m_queue_list_stop_id = 0;
std::vector<Notifications> empty_notifications;
m_notifications.swap(empty_notifications);
m_image_tokens.clear();
@@ -1235,7 +1243,7 @@ Process::GetNextEvent (EventSP &event_sp)
StateType
-Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always)
+Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always, Listener *hijack_listener)
{
// We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
// We have to actually check each event, and in the case of a stopped event check the restarted flag
@@ -1264,7 +1272,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp
while (state != eStateInvalid)
{
EventSP event_sp;
- state = WaitForStateChangedEvents (timeout, event_sp);
+ state = WaitForStateChangedEvents (timeout, event_sp, hijack_listener);
if (event_sp_ptr && event_sp)
*event_sp_ptr = event_sp;
@@ -1274,12 +1282,22 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp
case eStateDetached:
case eStateExited:
case eStateUnloaded:
+ // We need to toggle the run lock as this won't get done in
+ // SetPublicState() if the process is hijacked.
+ if (hijack_listener)
+ m_public_run_lock.SetStopped();
return state;
case eStateStopped:
if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
continue;
else
+ {
+ // We need to toggle the run lock as this won't get done in
+ // SetPublicState() if the process is hijacked.
+ if (hijack_listener)
+ m_public_run_lock.SetStopped();
return state;
+ }
default:
continue;
}
@@ -1292,7 +1310,8 @@ StateType
Process::WaitForState
(
const TimeValue *timeout,
- const StateType *match_states, const uint32_t num_match_states
+ const StateType *match_states,
+ const uint32_t num_match_states
)
{
EventSP event_sp;
@@ -1305,7 +1324,7 @@ Process::WaitForState
if (state == eStateDetached || state == eStateExited)
return state;
- state = WaitForStateChangedEvents (timeout, event_sp);
+ state = WaitForStateChangedEvents (timeout, event_sp, NULL);
for (i=0; i<num_match_states; ++i)
{
@@ -1351,18 +1370,22 @@ Process::RestorePrivateProcessEvents ()
}
StateType
-Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
+Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
+ Listener *listener = hijack_listener;
+ if (listener == NULL)
+ listener = &m_listener;
+
StateType state = eStateInvalid;
- if (m_listener.WaitForEventForBroadcasterWithType (timeout,
- this,
- eBroadcastBitStateChanged | eBroadcastBitInterrupt,
- event_sp))
+ if (listener->WaitForEventForBroadcasterWithType (timeout,
+ this,
+ eBroadcastBitStateChanged | eBroadcastBitInterrupt,
+ event_sp))
{
if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
@@ -1500,6 +1523,7 @@ Process::SetExitStatus (int status, const char *cstr)
DidExit ();
SetPrivateState (eStateExited);
+ CancelWatchForSTDIN (true);
return true;
}
@@ -1600,12 +1624,32 @@ Process::UpdateThreadListIfNeeded ()
// Clear any extended threads that we may have accumulated previously
m_extended_thread_list.Clear();
m_extended_thread_stop_id = GetLastNaturalStopID ();
+
+ m_queue_list.Clear();
+ m_queue_list_stop_id = GetLastNaturalStopID ();
}
}
}
}
}
+void
+Process::UpdateQueueListIfNeeded ()
+{
+ if (m_system_runtime_ap.get())
+ {
+ if (m_queue_list.GetSize() == 0 || m_queue_list_stop_id != GetLastNaturalStopID())
+ {
+ const StateType state = GetPrivateState();
+ if (StateIsStoppedState (state, true))
+ {
+ m_system_runtime_ap->PopulateQueueList (m_queue_list);
+ m_queue_list_stop_id = GetLastNaturalStopID();
+ }
+ }
+ }
+}
+
ThreadSP
Process::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context)
{
@@ -2084,7 +2128,60 @@ Process::EnableBreakpointSiteByID (lldb::user_id_t break_id)
lldb::break_id_t
Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardware)
{
- const addr_t load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ addr_t load_addr = LLDB_INVALID_ADDRESS;
+
+ bool show_error = true;
+ switch (GetState())
+ {
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateDetached:
+ case eStateExited:
+ show_error = false;
+ break;
+
+ case eStateStopped:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateCrashed:
+ case eStateSuspended:
+ show_error = IsAlive();
+ break;
+ }
+
+ // Reset the IsIndirect flag here, in case the location changes from
+ // pointing to a indirect symbol to a regular symbol.
+ owner->SetIsIndirect (false);
+
+ if (owner->ShouldResolveIndirectFunctions())
+ {
+ Symbol *symbol = owner->GetAddress().CalculateSymbolContextSymbol();
+ if (symbol && symbol->IsIndirect())
+ {
+ Error error;
+ load_addr = ResolveIndirectFunction (&symbol->GetAddress(), error);
+ if (!error.Success() && show_error)
+ {
+ m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ symbol->GetAddress().GetLoadAddress(&m_target),
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unkown error");
+ return LLDB_INVALID_BREAK_ID;
+ }
+ Address resolved_address(load_addr);
+ load_addr = resolved_address.GetOpcodeLoadAddress (&m_target);
+ owner->SetIsIndirect(true);
+ }
+ else
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ }
+ else
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+
if (load_addr != LLDB_INVALID_ADDRESS)
{
BreakpointSiteSP bp_site_sp;
@@ -2113,36 +2210,14 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
}
else
{
- bool show_error = true;
- switch (GetState())
- {
- case eStateInvalid:
- case eStateUnloaded:
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateDetached:
- case eStateExited:
- show_error = false;
- break;
-
- case eStateStopped:
- case eStateRunning:
- case eStateStepping:
- case eStateCrashed:
- case eStateSuspended:
- show_error = IsAlive();
- break;
- }
-
if (show_error)
{
// Report error for setting breakpoint...
- m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
- load_addr,
- owner->GetBreakpoint().GetID(),
- owner->GetID(),
- error.AsCString() ? error.AsCString() : "unkown error");
+ m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ load_addr,
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unkown error");
}
}
}
@@ -3153,7 +3228,7 @@ Process::Attach (ProcessAttachInfo &attach_info)
const bool restarted = false;
SetPublicState (eStateAttaching, restarted);
// Now attach using these arguments.
- error = DoAttachToProcessWithName (process_name, wait_for_launch, attach_info);
+ error = DoAttachToProcessWithName (process_name, attach_info);
}
else
{
@@ -3663,8 +3738,6 @@ Process::Destroy ()
}
m_stdio_communication.StopReadThread();
m_stdio_communication.Disconnect();
- if (m_process_input_reader && m_process_input_reader->IsActive())
- m_target.GetDebugger().PopInputReader (m_process_input_reader);
if (m_process_input_reader)
m_process_input_reader.reset();
@@ -3745,33 +3818,38 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
// stopped -> running: Report except when there is one or more no votes
// and no yes votes.
SynchronouslyNotifyStateChanged (state);
- switch (m_last_broadcast_state)
+ if (m_force_next_event_delivery)
+ return_value = true;
+ else
{
- case eStateRunning:
- case eStateStepping:
- // We always suppress multiple runnings with no PUBLIC stop in between.
- return_value = false;
- break;
- default:
- // TODO: make this work correctly. For now always report
- // run if we aren't running so we don't miss any runnning
- // events. If I run the lldb/test/thread/a.out file and
- // break at main.cpp:58, run and hit the breakpoints on
- // multiple threads, then somehow during the stepping over
- // of all breakpoints no run gets reported.
-
- // This is a transition from stop to run.
- switch (m_thread_list.ShouldReportRun (event_ptr))
- {
- case eVoteYes:
- case eVoteNoOpinion:
- return_value = true;
- break;
- case eVoteNo:
- return_value = false;
- break;
- }
- break;
+ switch (m_last_broadcast_state)
+ {
+ case eStateRunning:
+ case eStateStepping:
+ // We always suppress multiple runnings with no PUBLIC stop in between.
+ return_value = false;
+ break;
+ default:
+ // TODO: make this work correctly. For now always report
+ // run if we aren't running so we don't miss any runnning
+ // events. If I run the lldb/test/thread/a.out file and
+ // break at main.cpp:58, run and hit the breakpoints on
+ // multiple threads, then somehow during the stepping over
+ // of all breakpoints no run gets reported.
+
+ // This is a transition from stop to run.
+ switch (m_thread_list.ShouldReportRun (event_ptr))
+ {
+ case eVoteYes:
+ case eVoteNoOpinion:
+ return_value = true;
+ break;
+ case eVoteNo:
+ return_value = false;
+ break;
+ }
+ break;
+ }
}
break;
case eStateStopped:
@@ -3844,6 +3922,9 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
break;
}
+ // Forcing the next event delivery is a one shot deal. So reset it here.
+ m_force_next_event_delivery = false;
+
// We do some coalescing of events (for instance two consecutive running events get coalesced.)
// But we only coalesce against events we actually broadcast. So we use m_last_broadcast_state
// to track that. NB - you can't use "m_public_state.GetValue()" for that purpose, as was originally done,
@@ -4046,9 +4127,14 @@ Process::HandlePrivateEvent (EventSP &event_sp)
}
Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
if (StateIsRunningState (new_state))
- PushProcessInputReader ();
+ {
+ // Only push the input handler if we aren't fowarding events,
+ // as this means the curses GUI is in use...
+ if (!GetTarget().GetDebugger().IsForwardingEvents())
+ PushProcessIOHandler ();
+ }
else if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
- PopProcessInputReader ();
+ PopProcessIOHandler ();
BroadcastEvent (event_sp);
}
@@ -4594,64 +4680,203 @@ Process::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_
process->AppendSTDOUT (static_cast<const char *>(src), src_len);
}
-size_t
-Process::ProcessInputReaderCallback (void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len)
+void
+Process::ResetProcessIOHandler ()
+{
+ m_process_input_reader.reset();
+}
+
+
+class IOHandlerProcessSTDIO :
+ public IOHandler
{
- Process *process = (Process *) baton;
-
- switch (notification)
+public:
+ IOHandlerProcessSTDIO (Process *process,
+ int write_fd) :
+ IOHandler(process->GetTarget().GetDebugger()),
+ m_process (process),
+ m_read_file (),
+ m_write_file (write_fd, false),
+ m_pipe_read(),
+ m_pipe_write()
+ {
+ m_read_file.SetDescriptor(GetInputFD(), false);
+ }
+
+ virtual
+ ~IOHandlerProcessSTDIO ()
{
- case eInputReaderActivate:
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderReactivate:
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
- case eInputReaderGotToken:
+ }
+
+ bool
+ OpenPipes ()
+ {
+ if (m_pipe_read.IsValid() && m_pipe_write.IsValid())
+ return true;
+
+ int fds[2];
+#ifdef _MSC_VER
+ // pipe is not supported on windows so default to a fail condition
+ int err = 1;
+#else
+ int err = pipe(fds);
+#endif
+ if (err == 0)
{
- Error error;
- process->PutSTDIN (bytes, bytes_len, error);
+ m_pipe_read.SetDescriptor(fds[0], true);
+ m_pipe_write.SetDescriptor(fds[1], true);
+ return true;
}
- break;
+ return false;
+ }
+
+ void
+ ClosePipes()
+ {
+ m_pipe_read.Close();
+ m_pipe_write.Close();
+ }
+
+ // Each IOHandler gets to run until it is done. It should read data
+ // from the "in" and place output into "out" and "err and return
+ // when done.
+ virtual void
+ Run ()
+ {
+ if (m_read_file.IsValid() && m_write_file.IsValid())
+ {
+ SetIsDone(false);
+ if (OpenPipes())
+ {
+ const int read_fd = m_read_file.GetDescriptor();
+ const int pipe_read_fd = m_pipe_read.GetDescriptor();
+ TerminalState terminal_state;
+ terminal_state.Save (read_fd, false);
+ Terminal terminal(read_fd);
+ terminal.SetCanonical(false);
+ terminal.SetEcho(false);
+// FD_ZERO, FD_SET are not supported on windows
+#ifndef _MSC_VER
+ while (!GetIsDone())
+ {
+ fd_set read_fdset;
+ FD_ZERO (&read_fdset);
+ FD_SET (read_fd, &read_fdset);
+ FD_SET (pipe_read_fd, &read_fdset);
+ const int nfds = std::max<int>(read_fd, pipe_read_fd) + 1;
+ int num_set_fds = select (nfds, &read_fdset, NULL, NULL, NULL);
+ if (num_set_fds < 0)
+ {
+ const int select_errno = errno;
+
+ if (select_errno != EINTR)
+ SetIsDone(true);
+ }
+ else if (num_set_fds > 0)
+ {
+ char ch = 0;
+ size_t n;
+ if (FD_ISSET (read_fd, &read_fdset))
+ {
+ n = 1;
+ if (m_read_file.Read(&ch, n).Success() && n == 1)
+ {
+ if (m_write_file.Write(&ch, n).Fail() || n != 1)
+ SetIsDone(true);
+ }
+ else
+ SetIsDone(true);
+ }
+ if (FD_ISSET (pipe_read_fd, &read_fdset))
+ {
+ // Consume the interrupt byte
+ n = 1;
+ m_pipe_read.Read (&ch, n);
+ SetIsDone(true);
+ }
+ }
+ }
+#endif
+ terminal_state.Restore();
+
+ }
+ else
+ SetIsDone(true);
+ }
+ else
+ SetIsDone(true);
+ }
+
+ // Hide any characters that have been displayed so far so async
+ // output can be displayed. Refresh() will be called after the
+ // output has been displayed.
+ virtual void
+ Hide ()
+ {
- case eInputReaderInterrupt:
- process->SendAsyncInterrupt();
- break;
-
- case eInputReaderEndOfFile:
- process->AppendSTDOUT ("^D", 2);
- break;
+ }
+ // Called when the async output has been received in order to update
+ // the input reader (refresh the prompt and redisplay any current
+ // line(s) that are being edited
+ virtual void
+ Refresh ()
+ {
- case eInputReaderDone:
- break;
+ }
+
+ virtual void
+ Cancel ()
+ {
+ size_t n = 1;
+ char ch = 'q';
+ m_pipe_write.Write (&ch, n);
+ }
+
+ virtual void
+ Interrupt ()
+ {
+ if (StateIsRunningState(m_process->GetState()))
+ m_process->SendAsyncInterrupt();
+ }
+
+ virtual void
+ GotEOF()
+ {
}
- return bytes_len;
+protected:
+ Process *m_process;
+ File m_read_file; // Read from this file (usually actual STDIN for LLDB
+ File m_write_file; // Write to this file (usually the master pty for getting io to debuggee)
+ File m_pipe_read;
+ File m_pipe_write;
+
+};
+
+void
+Process::WatchForSTDIN (IOHandler &io_handler)
+{
}
void
-Process::ResetProcessInputReader ()
-{
- m_process_input_reader.reset();
+Process::CancelWatchForSTDIN (bool exited)
+{
+ if (m_process_input_reader)
+ {
+ if (exited)
+ m_process_input_reader->SetIsDone(true);
+ m_process_input_reader->Cancel();
+ }
}
void
-Process::SetSTDIOFileDescriptor (int file_descriptor)
+Process::SetSTDIOFileDescriptor (int fd)
{
// First set up the Read Thread for reading/handling process I/O
- std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (file_descriptor, true));
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (fd, true));
if (conn_ap.get())
{
@@ -4664,70 +4889,37 @@ Process::SetSTDIOFileDescriptor (int file_descriptor)
// Now read thread is set up, set up input reader.
if (!m_process_input_reader.get())
- {
- m_process_input_reader.reset (new InputReader(m_target.GetDebugger()));
- Error err (m_process_input_reader->Initialize (Process::ProcessInputReaderCallback,
- this,
- eInputReaderGranularityByte,
- NULL,
- NULL,
- false));
-
- if (err.Fail())
- m_process_input_reader.reset();
- }
+ m_process_input_reader.reset (new IOHandlerProcessSTDIO (this, fd));
}
}
}
void
-Process::PushProcessInputReader ()
+Process::PushProcessIOHandler ()
{
- if (m_process_input_reader && !m_process_input_reader->IsActive())
- m_target.GetDebugger().PushInputReader (m_process_input_reader);
+ IOHandlerSP io_handler_sp (m_process_input_reader);
+ if (io_handler_sp)
+ {
+ io_handler_sp->SetIsDone(false);
+ m_target.GetDebugger().PushIOHandler (io_handler_sp);
+ }
}
void
-Process::PopProcessInputReader ()
+Process::PopProcessIOHandler ()
{
- if (m_process_input_reader && m_process_input_reader->IsActive())
- m_target.GetDebugger().PopInputReader (m_process_input_reader);
+ IOHandlerSP io_handler_sp (m_process_input_reader);
+ if (io_handler_sp)
+ {
+ io_handler_sp->Cancel();
+ m_target.GetDebugger().PopIOHandler (io_handler_sp);
+ }
}
// The process needs to know about installed plug-ins
void
Process::SettingsInitialize ()
{
-// static std::vector<OptionEnumValueElement> g_plugins;
-//
-// int i=0;
-// const char *name;
-// OptionEnumValueElement option_enum;
-// while ((name = PluginManager::GetProcessPluginNameAtIndex (i)) != NULL)
-// {
-// if (name)
-// {
-// option_enum.value = i;
-// option_enum.string_value = name;
-// option_enum.usage = PluginManager::GetProcessPluginDescriptionAtIndex (i);
-// g_plugins.push_back (option_enum);
-// }
-// ++i;
-// }
-// option_enum.value = 0;
-// option_enum.string_value = NULL;
-// option_enum.usage = NULL;
-// g_plugins.push_back (option_enum);
-//
-// for (i=0; (name = SettingsController::instance_settings_table[i].var_name); ++i)
-// {
-// if (::strcmp (name, "plugin") == 0)
-// {
-// SettingsController::instance_settings_table[i].enum_values = &g_plugins[0];
-// break;
-// }
-// }
-//
Thread::SettingsInitialize ();
}
@@ -4925,6 +5117,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
final_timeout.OffsetWithMicroSeconds(timeout_usec);
}
+ // This isn't going to work if there are unfetched events on the queue.
+ // Are there cases where we might want to run the remaining events here, and then try to
+ // call the function? That's probably being too tricky for our own good.
+
+ Event *other_events = listener.PeekAtNextEvent();
+ if (other_events != NULL)
+ {
+ errors.Printf("Calling RunThreadPlan with pending events on the queue.");
+ return eExecutionSetupError;
+ }
+
+ // We also need to make sure that the next event is delivered. We might be calling a function as part of
+ // a thread plan, in which case the last delivered event could be the running event, and we don't want
+ // event coalescing to cause us to lose OUR running event...
+ ForceNextEventDelivery();
+
// This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
// So don't call return anywhere within it.
@@ -5680,6 +5888,10 @@ void
Process::Flush ()
{
m_thread_list.Flush();
+ m_extended_thread_list.Flush();
+ m_extended_thread_stop_id = 0;
+ m_queue_list.Clear();
+ m_queue_list_stop_id = 0;
}
void
@@ -5709,3 +5921,37 @@ Process::DidExec ()
target.DidExec();
}
+addr_t
+Process::ResolveIndirectFunction(const Address *address, Error &error)
+{
+ if (address == nullptr)
+ {
+ error.SetErrorString("Invalid address argument");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ addr_t function_addr = LLDB_INVALID_ADDRESS;
+
+ addr_t addr = address->GetLoadAddress(&GetTarget());
+ std::map<addr_t,addr_t>::const_iterator iter = m_resolved_indirect_addresses.find(addr);
+ if (iter != m_resolved_indirect_addresses.end())
+ {
+ function_addr = (*iter).second;
+ }
+ else
+ {
+ if (!InferiorCall(this, address, function_addr))
+ {
+ Symbol *symbol = address->CalculateSymbolContextSymbol();
+ error.SetErrorStringWithFormat ("Unable to call resolver for indirect function %s",
+ symbol ? symbol->GetName().AsCString() : "<UNKNOWN>");
+ function_addr = LLDB_INVALID_ADDRESS;
+ }
+ else
+ {
+ m_resolved_indirect_addresses.insert(std::pair<addr_t, addr_t>(addr, function_addr));
+ }
+ }
+ return function_addr;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Target/Queue.cpp b/contrib/llvm/tools/lldb/source/Target/Queue.cpp
new file mode 100644
index 0000000..2b9d2a0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/Queue.cpp
@@ -0,0 +1,127 @@
+//===-- Queue.cpp -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Queue.h"
+#include "lldb/Target/QueueList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/SystemRuntime.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Queue::Queue (ProcessSP process_sp, lldb::queue_id_t queue_id, const char *queue_name) :
+ m_process_wp (),
+ m_queue_id (queue_id),
+ m_queue_name (),
+ m_running_work_items_count(0),
+ m_pending_work_items_count(0),
+ m_pending_items(),
+ m_dispatch_queue_t_addr(LLDB_INVALID_ADDRESS)
+{
+ if (queue_name)
+ m_queue_name = queue_name;
+
+ m_process_wp = process_sp;
+}
+
+Queue::~Queue ()
+{
+}
+
+queue_id_t
+Queue::GetID ()
+{
+ return m_queue_id;
+}
+
+const char *
+Queue::GetName ()
+{
+ const char *result = NULL;
+ if (m_queue_name.size() > 0)
+ result = m_queue_name.c_str();
+ return result;
+}
+
+uint32_t
+Queue::GetIndexID ()
+{
+ return m_queue_id;
+}
+
+std::vector<lldb::ThreadSP>
+Queue::GetThreads ()
+{
+ std::vector<ThreadSP> result;
+ ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp.get ())
+ {
+ for (ThreadSP thread_sp : process_sp->Threads())
+ {
+ if (thread_sp->GetQueueID() == m_queue_id)
+ {
+ result.push_back (thread_sp);
+ }
+ }
+ }
+ return result;
+}
+
+void
+Queue::SetNumRunningWorkItems (uint32_t count)
+{
+ m_running_work_items_count = count;
+}
+
+uint32_t
+Queue::GetNumRunningWorkItems () const
+{
+ return m_running_work_items_count;
+}
+
+
+void
+Queue::SetNumPendingWorkItems (uint32_t count)
+{
+ m_pending_work_items_count = count;
+}
+
+uint32_t
+Queue::GetNumPendingWorkItems () const
+{
+ return m_pending_work_items_count;
+}
+
+void
+Queue::SetLibdispatchQueueAddress (addr_t dispatch_queue_t_addr)
+{
+ m_dispatch_queue_t_addr = dispatch_queue_t_addr;
+}
+
+addr_t
+Queue::GetLibdispatchQueueAddress () const
+{
+ return m_dispatch_queue_t_addr;
+}
+
+
+const std::vector<lldb::QueueItemSP> &
+Queue::GetPendingItems ()
+{
+ if (m_pending_items.size() == 0)
+ {
+ ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp && process_sp->GetSystemRuntime())
+ {
+ process_sp->GetSystemRuntime()->PopulatePendingItemsForQueue (this);
+ }
+ }
+ return m_pending_items;
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/QueueItem.cpp b/contrib/llvm/tools/lldb/source/Target/QueueItem.cpp
new file mode 100644
index 0000000..bb67628
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/QueueItem.cpp
@@ -0,0 +1,77 @@
+//===-- QueueItem.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Queue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/QueueItem.h"
+#include "lldb/Target/SystemRuntime.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+QueueItem::QueueItem (QueueSP queue_sp) :
+ m_queue_wp (),
+ m_kind (eQueueItemKindUnknown),
+ m_address (),
+ m_item_that_enqueued_this_ref (LLDB_INVALID_ADDRESS),
+ m_enqueueing_thread_id (LLDB_INVALID_THREAD_ID),
+ m_enqueueing_queue_id (LLDB_INVALID_QUEUE_ID),
+ m_target_queue_id (LLDB_INVALID_QUEUE_ID),
+ m_stop_id (0),
+ m_backtrace(),
+ m_thread_label(),
+ m_queue_label(),
+ m_target_queue_label()
+{
+ m_queue_wp = queue_sp;
+}
+
+QueueItem::~QueueItem ()
+{
+}
+
+QueueItemKind
+QueueItem::GetKind() const
+{
+ return m_kind;
+}
+
+void
+QueueItem::SetKind (QueueItemKind item_kind)
+{
+ m_kind = item_kind;
+}
+
+Address &
+QueueItem::GetAddress ()
+{
+ return m_address;
+}
+
+void
+QueueItem::SetAddress (Address addr)
+{
+ m_address = addr;
+}
+
+ThreadSP
+QueueItem::GetExtendedBacktraceThread (ConstString type)
+{
+ ThreadSP return_thread;
+ QueueSP queue_sp = m_queue_wp.lock();
+ if (queue_sp)
+ {
+ ProcessSP process_sp = queue_sp->GetProcess();
+ if (process_sp && process_sp->GetSystemRuntime())
+ {
+ return_thread = process_sp->GetSystemRuntime()->GetExtendedBacktraceForQueueItem (this->shared_from_this(), type);
+ }
+ }
+ return return_thread;
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/QueueList.cpp b/contrib/llvm/tools/lldb/source/Target/QueueList.cpp
new file mode 100644
index 0000000..6134f5c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/QueueList.cpp
@@ -0,0 +1,102 @@
+//===-- QueueList.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Queue.h"
+#include "lldb/Target/QueueList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+QueueList::QueueList (Process *process) :
+ m_process (process),
+ m_stop_id (0),
+ m_queues (),
+ m_mutex ()
+{
+}
+
+QueueList::~QueueList ()
+{
+ Clear();
+}
+
+uint32_t
+QueueList::GetSize ()
+{
+ Mutex::Locker locker (m_mutex);
+ return m_queues.size();
+}
+
+lldb::QueueSP
+QueueList::GetQueueAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (m_mutex);
+ if (idx < m_queues.size())
+ {
+ return m_queues[idx];
+ }
+ else
+ {
+ return QueueSP();
+ }
+}
+
+void
+QueueList::Clear ()
+{
+ Mutex::Locker locker (m_mutex);
+ m_queues.clear();
+}
+
+void
+QueueList::AddQueue (QueueSP queue_sp)
+{
+ Mutex::Locker locker (m_mutex);
+ if (queue_sp.get ())
+ {
+ m_queues.push_back (queue_sp);
+ }
+}
+
+lldb::QueueSP
+QueueList::FindQueueByID (lldb::queue_id_t qid)
+{
+ QueueSP ret;
+ for (QueueSP queue_sp : Queues())
+ {
+ if (queue_sp->GetID() == qid)
+ {
+ ret = queue_sp;
+ break;
+ }
+ }
+ return ret;
+}
+
+lldb::QueueSP
+QueueList::FindQueueByIndexID (uint32_t index_id)
+{
+ QueueSP ret;
+ for (QueueSP queue_sp : Queues())
+ {
+ if (queue_sp->GetIndexID() == index_id)
+ {
+ ret = queue_sp;
+ break;
+ }
+ }
+ return ret;
+}
+
+lldb_private::Mutex &
+QueueList::GetMutex ()
+{
+ return m_mutex;
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp b/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp
new file mode 100644
index 0000000..527168c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/SectionLoadHistory.cpp
@@ -0,0 +1,182 @@
+//===-- SectionLoadHistory.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/SectionLoadHistory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Target/SectionLoadList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+bool
+SectionLoadHistory::IsEmpty() const
+{
+ Mutex::Locker locker(m_mutex);
+ return m_stop_id_to_section_load_list.empty();
+}
+
+void
+SectionLoadHistory::Clear ()
+{
+ Mutex::Locker locker(m_mutex);
+ m_stop_id_to_section_load_list.clear();
+}
+
+uint32_t
+SectionLoadHistory::GetLastStopID() const
+{
+ Mutex::Locker locker(m_mutex);
+ if (m_stop_id_to_section_load_list.empty())
+ return 0;
+ else
+ return m_stop_id_to_section_load_list.rbegin()->first;
+}
+
+SectionLoadList *
+SectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_only)
+{
+ if (m_stop_id_to_section_load_list.empty())
+ {
+ SectionLoadListSP section_load_list_sp(new SectionLoadList());
+ if (stop_id == eStopIDNow)
+ stop_id = 0;
+ m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
+ return section_load_list_sp.get();
+ }
+ else
+ {
+ if (read_only)
+ {
+ // The section load list is for reading data only so we don't need to create
+ // a new SectionLoadList for the current stop ID, just return the section
+ // load list for the stop ID that is equal to or less than the current stop ID
+ if (stop_id == eStopIDNow)
+ {
+ // If we are asking for the latest and greatest value, it is always
+ // at the end of our list becuase that will be the highest stop ID.
+ StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
+ return rpos->second.get();
+ }
+ else
+ {
+ StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
+ if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
+ return pos->second.get();
+ else if (pos != m_stop_id_to_section_load_list.begin())
+ {
+ --pos;
+ return pos->second.get();
+ }
+ }
+ }
+ else
+ {
+ // You can only use "eStopIDNow" when reading from the section load history
+ assert(stop_id != eStopIDNow);
+
+ // We are updating the section load list (not read only), so if the stop ID
+ // passed in isn't the same as the last stop ID in our collection, then create
+ // a new node using the current stop ID
+ StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
+ if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
+ {
+ // We already have an entry for this value
+ return pos->second.get();
+ }
+
+ // We must make a new section load list that is based on the last valid
+ // section load list, so here we copy the last section load list and add
+ // a new node for the current stop ID.
+ StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
+ SectionLoadListSP section_load_list_sp(new SectionLoadList(*rpos->second.get()));
+ m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
+ return section_load_list_sp.get();
+ }
+ }
+ return NULL;
+}
+
+SectionLoadList &
+SectionLoadHistory::GetCurrentSectionLoadList ()
+{
+ const bool read_only = true;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (eStopIDNow, read_only);
+ assert(section_load_list != NULL);
+ return *section_load_list;
+}
+
+addr_t
+SectionLoadHistory::GetSectionLoadAddress (uint32_t stop_id, const lldb::SectionSP &section_sp)
+{
+ Mutex::Locker locker(m_mutex);
+ const bool read_only = true;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
+ return section_load_list->GetSectionLoadAddress(section_sp);
+}
+
+bool
+SectionLoadHistory::ResolveLoadAddress (uint32_t stop_id, addr_t load_addr, Address &so_addr)
+{
+ // First find the top level section that this load address exists in
+ Mutex::Locker locker(m_mutex);
+ const bool read_only = true;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
+ return section_load_list->ResolveLoadAddress (load_addr, so_addr);
+}
+
+bool
+SectionLoadHistory::SetSectionLoadAddress (uint32_t stop_id,
+ const lldb::SectionSP &section_sp,
+ addr_t load_addr,
+ bool warn_multiple)
+{
+ Mutex::Locker locker(m_mutex);
+ const bool read_only = false;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
+ return section_load_list->SetSectionLoadAddress(section_sp, load_addr, warn_multiple);
+}
+
+size_t
+SectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp)
+{
+ Mutex::Locker locker(m_mutex);
+ const bool read_only = false;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
+ return section_load_list->SetSectionUnloaded (section_sp);
+}
+
+bool
+SectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr)
+{
+ Mutex::Locker locker(m_mutex);
+ const bool read_only = false;
+ SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
+ return section_load_list->SetSectionUnloaded (section_sp, load_addr);
+}
+
+void
+SectionLoadHistory::Dump (Stream &s, Target *target)
+{
+ Mutex::Locker locker(m_mutex);
+ StopIDToSectionLoadList::iterator pos, end = m_stop_id_to_section_load_list.end();
+ for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos)
+ {
+ s.Printf("StopID = %u:\n", pos->first);
+ pos->second->Dump(s, target);
+ s.EOL();
+ }
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp b/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
index 96713c6..82f52f9 100644
--- a/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/SectionLoadList.cpp
@@ -25,6 +25,25 @@ using namespace lldb;
using namespace lldb_private;
+SectionLoadList::SectionLoadList (const SectionLoadList& rhs) :
+ m_addr_to_sect(),
+ m_sect_to_addr(),
+ m_mutex (Mutex::eMutexTypeRecursive)
+{
+ Mutex::Locker locker(rhs.m_mutex);
+ m_addr_to_sect = rhs.m_addr_to_sect;
+ m_sect_to_addr = rhs.m_sect_to_addr;
+}
+
+void
+SectionLoadList::operator=(const SectionLoadList &rhs)
+{
+ Mutex::Locker lhs_locker (m_mutex);
+ Mutex::Locker rhs_locker (rhs.m_mutex);
+ m_addr_to_sect = rhs.m_addr_to_sect;
+ m_sect_to_addr = rhs.m_sect_to_addr;
+}
+
bool
SectionLoadList::IsEmpty() const
{
diff --git a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
index 914969a..3664e8f 100644
--- a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
@@ -419,8 +419,15 @@ protected:
// The breakpoint site may have many locations associated with it, not all of them valid for
// this thread. Skip the ones that aren't:
if (!bp_loc_sp->ValidForThisThread(thread_sp.get()))
+ {
+ if (log)
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
+ log->Printf ("Breakpoint %s hit on thread 0x%llx but it was not for this thread, continuing.", s.GetData(), thread_sp->GetID());
+ }
continue;
-
+ }
// First run the condition for the breakpoint. If that says we should stop, then we'll run
// the callback for the breakpoint. If the callback says we shouldn't stop that will win.
@@ -450,6 +457,12 @@ protected:
}
else
{
+ if (log)
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
+ log->Printf ("Condition evaluated for breakpoint %s on thread 0x%llx conditon_says_stop: %i.", s.GetData(), thread_sp->GetID(), condition_says_stop);
+ }
if (!condition_says_stop)
continue;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp
index 5c07ed3..c3fb9c8 100644
--- a/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp
@@ -56,6 +56,11 @@ SystemRuntime::DidLaunch()
}
void
+SystemRuntime::Detach()
+{
+}
+
+void
SystemRuntime::ModulesDidLoad (ModuleList &module_list)
{
}
diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp
index fd9626a..e781626 100644
--- a/contrib/llvm/tools/lldb/source/Target/Target.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp
@@ -28,6 +28,8 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/SourceManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
@@ -42,6 +44,7 @@
#include "lldb/lldb-private-log.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
@@ -69,12 +72,11 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_mutex (Mutex::eMutexTypeRecursive),
m_arch (target_arch),
m_images (this),
- m_section_load_list (),
+ m_section_load_history (),
m_breakpoint_list (false),
m_internal_breakpoint_list (true),
m_watchpoint_list (),
m_process_sp (),
- m_valid (true),
m_search_filter_sp (),
m_image_search_paths (ImageSearchPathsChanged, this),
m_scratch_ast_context_ap (),
@@ -84,6 +86,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_source_manager_ap(),
m_stop_hooks (),
m_stop_hook_next_id (0),
+ m_valid (true),
m_suppress_stop_hooks (false)
{
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
@@ -158,7 +161,7 @@ Target::DeleteCurrentProcess ()
{
if (m_process_sp.get())
{
- m_section_load_list.Clear();
+ m_section_load_history.Clear();
if (m_process_sp->IsAlive())
m_process_sp->Destroy();
@@ -193,7 +196,7 @@ Target::Destroy()
m_platform_sp.reset();
m_arch.Clear();
ClearModules(true);
- m_section_load_list.Clear();
+ m_section_load_history.Clear();
const bool notify = false;
m_breakpoint_list.RemoveAll(notify);
m_internal_breakpoint_list.RemoveAll(notify);
@@ -248,7 +251,7 @@ Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
{
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list));
BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -302,7 +305,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
line_no,
check_inlines,
skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -314,7 +317,7 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
// it doesn't resolve to section/offset.
// Try and resolve as a load address if possible
- m_section_load_list.ResolveLoadAddress(addr, so_addr);
+ GetSectionLoadList().ResolveLoadAddress(addr, so_addr);
if (!so_addr.IsValid())
{
// The address didn't resolve, so just set this as an absolute address
@@ -329,7 +332,7 @@ Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
{
SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false);
}
BreakpointSP
@@ -354,7 +357,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_name_type_mask,
Breakpoint::Exact,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -381,7 +384,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
func_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -409,7 +412,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
num_names,
func_name_type_mask,
skip_prologue));
- bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
}
@@ -487,7 +490,7 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
func_regex,
skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue));
- return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware);
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
lldb::BreakpointSP
@@ -497,12 +500,12 @@ Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_
}
BreakpointSP
-Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware)
+Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware, bool resolve_indirect_symbols)
{
BreakpointSP bp_sp;
if (filter_sp && resolver_sp)
{
- bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware));
+ bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware, resolve_indirect_symbols));
resolver_sp->SetBreakpoint (bp_sp.get());
if (internal)
@@ -1004,11 +1007,11 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target)
if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error, &feedback_stream))
{
if (error.AsCString())
- target->GetDebugger().GetErrorStream().Printf("unable to load scripting data for module %s - error reported was %s\n",
+ target->GetDebugger().GetErrorFile()->Printf("unable to load scripting data for module %s - error reported was %s\n",
module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
error.AsCString());
if (feedback_stream.GetSize())
- target->GetDebugger().GetOutputStream().Printf("%s\n",
+ target->GetDebugger().GetErrorFile()->Printf("%s\n",
feedback_stream.GetData());
}
}
@@ -1017,7 +1020,7 @@ void
Target::ClearModules(bool delete_locations)
{
ModulesDidUnload (m_images, delete_locations);
- GetSectionLoadList().Clear();
+ m_section_load_history.Clear();
m_images.Clear();
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
@@ -1065,7 +1068,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
FileSpec dependent_file_spec (dependent_files.GetFileSpecPointerAtIndex(i));
FileSpec platform_dependent_file_spec;
if (m_platform_sp)
- m_platform_sp->GetFile (dependent_file_spec, NULL, platform_dependent_file_spec);
+ m_platform_sp->GetFileWithUUID (dependent_file_spec, NULL, platform_dependent_file_spec);
else
platform_dependent_file_spec = dependent_file_spec;
@@ -1307,7 +1310,8 @@ Target::ReadMemory (const Address& addr,
Address resolved_addr;
if (!addr.IsSectionOffset())
{
- if (m_section_load_list.IsEmpty())
+ SectionLoadList &section_load_list = GetSectionLoadList();
+ if (section_load_list.IsEmpty())
{
// No sections are loaded, so we must assume we are not running
// yet and anything we are given is a file address.
@@ -1321,7 +1325,7 @@ Target::ReadMemory (const Address& addr,
// or because we have have a live process that has sections loaded
// through the dynamic loader
load_addr = addr.GetOffset(); // "addr" doesn't have a section, so its offset is the load address
- m_section_load_list.ResolveLoadAddress (load_addr, resolved_addr);
+ section_load_list.ResolveLoadAddress (load_addr, resolved_addr);
}
}
if (!resolved_addr.IsValid())
@@ -1534,7 +1538,8 @@ Target::ReadPointerFromMemory (const Address& addr,
addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
if (pointer_vm_addr != LLDB_INVALID_ADDRESS)
{
- if (m_section_load_list.IsEmpty())
+ SectionLoadList &section_load_list = GetSectionLoadList();
+ if (section_load_list.IsEmpty())
{
// No sections are loaded, so we must assume we are not running
// yet and anything we are given is a file address.
@@ -1546,7 +1551,7 @@ Target::ReadPointerFromMemory (const Address& addr,
// we have manually loaded some sections with "target modules load ..."
// or because we have have a live process that has sections loaded
// through the dynamic loader
- m_section_load_list.ResolveLoadAddress (pointer_vm_addr, pointer_addr);
+ section_load_list.ResolveLoadAddress (pointer_vm_addr, pointer_addr);
}
// We weren't able to resolve the pointer value, so just return
// an address with no section
@@ -1994,13 +1999,13 @@ Target::GetSourceManager ()
}
-lldb::user_id_t
-Target::AddStopHook (Target::StopHookSP &new_hook_sp)
+Target::StopHookSP
+Target::CreateStopHook ()
{
lldb::user_id_t new_uid = ++m_stop_hook_next_id;
- new_hook_sp.reset (new StopHook(shared_from_this(), new_uid));
- m_stop_hooks[new_uid] = new_hook_sp;
- return new_uid;
+ Target::StopHookSP stop_hook_sp (new StopHook(shared_from_this(), new_uid));
+ m_stop_hooks[new_uid] = stop_hook_sp;
+ return stop_hook_sp;
}
bool
@@ -2259,6 +2264,186 @@ Target::Install (ProcessLaunchInfo *launch_info)
return error;
}
+bool
+Target::ResolveLoadAddress (addr_t load_addr, Address &so_addr, uint32_t stop_id)
+{
+ return m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr);
+}
+
+bool
+Target::SetSectionLoadAddress (const SectionSP &section_sp, addr_t new_section_load_addr, bool warn_multiple)
+{
+ const addr_t old_section_load_addr = m_section_load_history.GetSectionLoadAddress (SectionLoadHistory::eStopIDNow, section_sp);
+ if (old_section_load_addr != new_section_load_addr)
+ {
+ uint32_t stop_id = 0;
+ ProcessSP process_sp(GetProcessSP());
+ if (process_sp)
+ stop_id = process_sp->GetStopID();
+ else
+ stop_id = m_section_load_history.GetLastStopID();
+ if (m_section_load_history.SetSectionLoadAddress (stop_id, section_sp, new_section_load_addr, warn_multiple))
+ return true; // Return true if the section load address was changed...
+ }
+ return false; // Return false to indicate nothing changed
+
+}
+
+bool
+Target::SetSectionUnloaded (const lldb::SectionSP &section_sp)
+{
+ uint32_t stop_id = 0;
+ ProcessSP process_sp(GetProcessSP());
+ if (process_sp)
+ stop_id = process_sp->GetStopID();
+ else
+ stop_id = m_section_load_history.GetLastStopID();
+ return m_section_load_history.SetSectionUnloaded (stop_id, section_sp);
+}
+
+bool
+Target::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
+{
+ uint32_t stop_id = 0;
+ ProcessSP process_sp(GetProcessSP());
+ if (process_sp)
+ stop_id = process_sp->GetStopID();
+ else
+ stop_id = m_section_load_history.GetLastStopID();
+ return m_section_load_history.SetSectionUnloaded (stop_id, section_sp, load_addr);
+}
+
+void
+Target::ClearAllLoadedSections ()
+{
+ m_section_load_history.Clear();
+}
+
+
+Error
+Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
+{
+ Error error;
+
+ StateType state = eStateInvalid;
+
+ // Scope to temporarily get the process state in case someone has manually
+ // remotely connected already to a process and we can skip the platform
+ // launching.
+ {
+ ProcessSP process_sp (GetProcessSP());
+
+ if (process_sp)
+ state = process_sp->GetState();
+ }
+
+ launch_info.GetFlags().Set (eLaunchFlagDebug);
+
+ // Get the value of synchronous execution here. If you wait till after you have started to
+ // run, then you could have hit a breakpoint, whose command might switch the value, and
+ // then you'll pick up that incorrect value.
+ Debugger &debugger = GetDebugger();
+ const bool synchronous_execution = debugger.GetCommandInterpreter().GetSynchronous ();
+
+ PlatformSP platform_sp (GetPlatform());
+
+ // Finalize the file actions, and if none were given, default to opening
+ // up a pseudo terminal
+ const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
+ launch_info.FinalizeFileActions (this, default_to_use_pty);
+
+ if (state == eStateConnected)
+ {
+ if (launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
+ {
+ error.SetErrorString("can't launch in tty when launching through a remote connection");
+ return error;
+ }
+ }
+
+ if (!launch_info.GetArchitecture().IsValid())
+ launch_info.GetArchitecture() = GetArchitecture();
+
+ if (state != eStateConnected && platform_sp && platform_sp->CanDebugProcess ())
+ {
+ m_process_sp = GetPlatform()->DebugProcess (launch_info,
+ debugger,
+ this,
+ listener,
+ error);
+ }
+ else
+ {
+ if (state == eStateConnected)
+ {
+ assert(m_process_sp);
+ }
+ else
+ {
+ const char *plugin_name = launch_info.GetProcessPluginName();
+ CreateProcess (listener, plugin_name, NULL);
+ }
+
+ if (m_process_sp)
+ error = m_process_sp->Launch (launch_info);
+ }
+
+ if (!m_process_sp)
+ {
+ if (error.Success())
+ error.SetErrorString("failed to launch or debug process");
+ return error;
+ }
+
+ if (error.Success())
+ {
+ if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
+ {
+ ListenerSP hijack_listener_sp (launch_info.GetHijackListener());
+
+ StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get());
+
+ if (state == eStateStopped)
+ {
+ if (!synchronous_execution)
+ m_process_sp->RestoreProcessEvents ();
+
+ error = m_process_sp->PrivateResume();
+
+ if (error.Success())
+ {
+ if (synchronous_execution)
+ {
+ state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get());
+ const bool must_be_alive = false; // eStateExited is ok, so this must be false
+ if (!StateIsStoppedState(state, must_be_alive))
+ {
+ error.SetErrorStringWithFormat("process isn't stopped: %s", StateAsCString(state));
+ }
+ }
+ }
+ else
+ {
+ Error error2;
+ error2.SetErrorStringWithFormat("process resume at entry point failed: %s", error.AsCString());
+ error = error2;
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
+ }
+ }
+ m_process_sp->RestoreProcessEvents ();
+ }
+ else
+ {
+ Error error2;
+ error2.SetErrorStringWithFormat ("process launch failed: %s", error.AsCString());
+ error = error2;
+ }
+ return error;
+}
//--------------------------------------------------------------
// Target::StopHook
//--------------------------------------------------------------
@@ -2452,6 +2637,8 @@ g_properties[] =
"'complete' is the default value for this setting which will load all sections and symbols by reading them from memory (slowest, most accurate). "
"'partial' will load sections and attempt to find function bounds without downloading the symbol table (faster, still accurate, missing symbol names). "
"'minimal' is the fastest setting and will load section data with no symbols, but should rarely be used as stack frames in these memory regions will be inaccurate and not provide any context (fastest). " },
+ { "display-expression-in-crashlogs" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true." },
+ { "trap-handler-names" , OptionValue::eTypeArray , true, OptionValue::eTypeString, NULL, NULL, "A list of trap handler function names, e.g. a common Unix user process one is _sigtramp." },
{ NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL }
};
enum
@@ -2483,7 +2670,9 @@ enum
ePropertyHexImmediateStyle,
ePropertyUseFastStepping,
ePropertyLoadScriptFromSymbolFile,
- ePropertyMemoryModuleLoadLevel
+ ePropertyMemoryModuleLoadLevel,
+ ePropertyDisplayExpressionsInCrashlogs,
+ ePropertyTrapHandlerNames
};
@@ -2862,6 +3051,13 @@ TargetProperties::GetUseFastStepping () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
+bool
+TargetProperties::GetDisplayExpressionsInCrashlogs () const
+{
+ const uint32_t idx = ePropertyDisplayExpressionsInCrashlogs;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
LoadScriptFromSymFile
TargetProperties::GetLoadScriptFromSymbolFile () const
{
@@ -2883,7 +3079,19 @@ TargetProperties::GetMemoryModuleLoadLevel() const
return (MemoryModuleLoadLevel)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
}
+bool
+TargetProperties::GetUserSpecifiedTrapHandlerNames (Args &args) const
+{
+ const uint32_t idx = ePropertyTrapHandlerNames;
+ return m_collection_sp->GetPropertyAtIndexAsArgs (NULL, idx, args);
+}
+void
+TargetProperties::SetUserSpecifiedTrapHandlerNames (const Args &args)
+{
+ const uint32_t idx = ePropertyTrapHandlerNames;
+ m_collection_sp->SetPropertyAtIndexFromArgs (NULL, idx, args);
+}
//----------------------------------------------------------------------
// Target::TargetEventData
diff --git a/contrib/llvm/tools/lldb/source/Target/Thread.cpp b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
index 07f5321..39f2699 100644
--- a/contrib/llvm/tools/lldb/source/Target/Thread.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
@@ -18,6 +18,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
@@ -61,12 +62,14 @@ static PropertyDefinition
g_properties[] =
{
{ "step-avoid-regexp", OptionValue::eTypeRegex , true , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
+ { "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , REG_EXTENDED, NULL, NULL, "A list of libraries that source stepping won't stop in." },
{ "trace-thread", OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
{ NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
};
enum {
ePropertyStepAvoidRegex,
+ ePropertyStepAvoidLibraries,
ePropertyEnableThreadTrace
};
@@ -132,6 +135,15 @@ ThreadProperties::GetSymbolsToAvoidRegexp()
return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex (NULL, idx);
}
+FileSpecList &
+ThreadProperties::GetLibrariesToAvoid() const
+{
+ const uint32_t idx = ePropertyStepAvoidLibraries;
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ assert(option_value);
+ return option_value->GetCurrentValue();
+}
+
bool
ThreadProperties::GetTraceEnabledState() const
{
@@ -2011,6 +2023,7 @@ Thread::GetUnwinder ()
case llvm::Triple::arm:
case llvm::Triple::thumb:
case llvm::Triple::mips64:
+ case llvm::Triple::hexagon:
m_unwinder_ap.reset (new UnwindLLDB (*this));
break;
@@ -2053,3 +2066,125 @@ Thread::IsStillAtLastBreakpointHit ()
}
return false;
}
+
+
+Error
+Thread::StepIn (bool source_step,
+ bool avoid_code_without_debug_info)
+
+{
+ Error error;
+ Process *process = GetProcess().get();
+ if (StateIsStoppedState (process->GetState(), true))
+ {
+ StackFrameSP frame_sp = GetStackFrameAtIndex (0);
+ ThreadPlanSP new_plan_sp;
+ const lldb::RunMode run_mode = eOnlyThisThread;
+ const bool abort_other_plans = false;
+
+ if (source_step && frame_sp && frame_sp->HasDebugInformation ())
+ {
+ SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+ new_plan_sp = QueueThreadPlanForStepInRange (abort_other_plans,
+ sc.line_entry.range,
+ sc,
+ NULL,
+ run_mode,
+ avoid_code_without_debug_info);
+ }
+ else
+ {
+ new_plan_sp = QueueThreadPlanForStepSingleInstruction (false,
+ abort_other_plans,
+ run_mode);
+ }
+
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+
+ // Why do we need to set the current thread by ID here???
+ process->GetThreadList().SetSelectedThreadByID (GetID());
+ error = process->Resume();
+ }
+ else
+ {
+ error.SetErrorString("process not stopped");
+ }
+ return error;
+}
+
+Error
+Thread::StepOver (bool source_step)
+
+{
+ Error error;
+ Process *process = GetProcess().get();
+ if (StateIsStoppedState (process->GetState(), true))
+ {
+ StackFrameSP frame_sp = GetStackFrameAtIndex (0);
+ ThreadPlanSP new_plan_sp;
+
+ const lldb::RunMode run_mode = eOnlyThisThread;
+ const bool abort_other_plans = false;
+
+ if (source_step && frame_sp && frame_sp->HasDebugInformation ())
+ {
+ SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+ new_plan_sp = QueueThreadPlanForStepOverRange (abort_other_plans,
+ sc.line_entry.range,
+ sc,
+ run_mode);
+ }
+ else
+ {
+ new_plan_sp = QueueThreadPlanForStepSingleInstruction (true,
+ abort_other_plans,
+ run_mode);
+ }
+
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+
+ // Why do we need to set the current thread by ID here???
+ process->GetThreadList().SetSelectedThreadByID (GetID());
+ error = process->Resume();
+ }
+ else
+ {
+ error.SetErrorString("process not stopped");
+ }
+ return error;
+}
+
+Error
+Thread::StepOut ()
+{
+ Error error;
+ Process *process = GetProcess().get();
+ if (StateIsStoppedState (process->GetState(), true))
+ {
+ const bool first_instruction = false;
+ const bool stop_other_threads = false;
+ const bool abort_other_plans = false;
+
+ ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut (abort_other_plans,
+ NULL,
+ first_instruction,
+ stop_other_threads,
+ eVoteYes,
+ eVoteNoOpinion,
+ 0));
+
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+
+ // Why do we need to set the current thread by ID here???
+ process->GetThreadList().SetSelectedThreadByID (GetID());
+ error = process->Resume();
+ }
+ else
+ {
+ error.SetErrorString("process not stopped");
+ }
+ return error;
+} \ No newline at end of file
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
index 1f8b351..4fffdac 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
@@ -85,6 +85,17 @@ ThreadList::AddThread (const ThreadSP &thread_sp)
m_threads.push_back(thread_sp);
}
+void
+ThreadList::InsertThread (const lldb::ThreadSP &thread_sp, uint32_t idx)
+{
+ Mutex::Locker locker(GetMutex());
+ if (idx < m_threads.size())
+ m_threads.insert(m_threads.begin() + idx, thread_sp);
+ else
+ m_threads.push_back (thread_sp);
+}
+
+
uint32_t
ThreadList::GetSize (bool can_update)
{
@@ -293,17 +304,31 @@ ThreadList::ShouldStop (Event *event_ptr)
{
ThreadSP thread_sp(*pos);
- did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
+ // We should never get a stop for which no thread had a stop reason, but sometimes we do see this -
+ // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out
+ // the right thing to do and stopping gives the user control over what to do in this instance.
+ //
+ // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint,
+ // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint
+ // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this
+ // code and causes us to stop seemingly for no reason.
+ //
+ // Since the only way we ever saw this error was on first attach, I'm only going to trigger set did_anybody_stop_for_a_reason
+ // to true unless this is the first stop.
+ //
+ // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid
+ // everywhere but at this check.
+
+ if (thread_sp->GetProcess()->GetStopID() > 1)
+ did_anybody_stop_for_a_reason = true;
+ else
+ did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
if (thread_should_stop)
should_stop |= true;
}
- // We should never get a stop for which no thread had a stop reason, but sometimes we do see this -
- // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out
- // the right thing to do and stopping gives the user control over what to do in this instance.
-
if (!should_stop && !did_anybody_stop_for_a_reason)
{
should_stop = true;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
index 2cfd29f..c4cb9ab 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -16,6 +16,7 @@
#include "lldb/lldb-private-log.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Function.h"
@@ -273,10 +274,36 @@ ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
}
bool
-ThreadPlanStepInRange::FrameMatchesAvoidRegexp ()
+ThreadPlanStepInRange::FrameMatchesAvoidCriteria ()
{
StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
+
+ // Check the library list first, as that's cheapest:
+ bool libraries_say_avoid = false;
+ FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid());
+ size_t num_libraries = libraries_to_avoid.GetSize();
+ if (num_libraries > 0)
+ {
+ SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule));
+ FileSpec frame_library(sc.module_sp->GetFileSpec());
+
+ if (frame_library)
+ {
+ for (size_t i = 0; i < num_libraries; i++)
+ {
+ const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i));
+ if (FileSpec::Equal (file_spec, frame_library, false))
+ {
+ libraries_say_avoid = true;
+ break;
+ }
+ }
+ }
+ }
+ if (libraries_say_avoid)
+ return true;
+
const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
if (avoid_regexp_to_use == NULL)
avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
@@ -368,8 +395,8 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
if (!should_step_out)
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
- // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidRegexp.
- should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
+ // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
+ should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
}
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
index 37cd03c..18da6cd 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -161,7 +161,7 @@ ThreadPlanStepThrough::ShouldStop (Event *event_ptr)
// First, did we hit the backstop breakpoint?
if (HitOurBackstopBreakpoint())
{
- SetPlanComplete(false);
+ SetPlanComplete(true);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
index af6cef7..d191170 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
@@ -23,11 +23,13 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -61,7 +63,7 @@ ThreadPlanTracer::GetLogStream ()
{
TargetSP target_sp (m_thread.CalculateTarget());
if (target_sp)
- return &target_sp->GetDebugger().GetOutputStream();
+ return target_sp->GetDebugger().GetOutputFile().get();
}
return NULL;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/UnwindAssembly.cpp b/contrib/llvm/tools/lldb/source/Target/UnwindAssembly.cpp
index 7213750..af7f86f 100644
--- a/contrib/llvm/tools/lldb/source/Target/UnwindAssembly.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/UnwindAssembly.cpp
@@ -15,7 +15,7 @@
using namespace lldb;
using namespace lldb_private;
-UnwindAssembly*
+UnwindAssemblySP
UnwindAssembly::FindPlugin (const ArchSpec &arch)
{
UnwindAssemblyCreateInstance create_callback;
@@ -24,9 +24,9 @@ UnwindAssembly::FindPlugin (const ArchSpec &arch)
(create_callback = PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(idx)) != NULL;
++idx)
{
- std::unique_ptr<UnwindAssembly> assembly_profiler_ap (create_callback (arch));
+ UnwindAssemblySP assembly_profiler_ap (create_callback (arch));
if (assembly_profiler_ap.get ())
- return assembly_profiler_ap.release ();
+ return assembly_profiler_ap;
}
return NULL;
}
OpenPOWER on IntegriCloud