aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/lldb/source/Target/Target.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/Target.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Target.cpp218
1 files changed, 166 insertions, 52 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp
index d2d0b5098555..e9393d1be0b4 100644
--- a/contrib/llvm/tools/lldb/source/Target/Target.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp
@@ -35,6 +35,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -63,7 +64,7 @@ Target::GetStaticBroadcasterClass ()
//----------------------------------------------------------------------
// Target constructor
//----------------------------------------------------------------------
-Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) :
+Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp, bool is_dummy_target) :
TargetProperties (this),
Broadcaster (&debugger, Target::GetStaticBroadcasterClass().AsCString()),
ExecutionContextScope (),
@@ -87,7 +88,9 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_stop_hooks (),
m_stop_hook_next_id (0),
m_valid (true),
- m_suppress_stop_hooks (false)
+ m_suppress_stop_hooks (false),
+ m_is_dummy_target(is_dummy_target)
+
{
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
@@ -106,6 +109,24 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
}
}
+void
+Target::PrimeFromDummyTarget(Target *target)
+{
+ if (!target)
+ return;
+
+ m_stop_hooks = target->m_stop_hooks;
+
+ for (BreakpointSP breakpoint_sp : target->m_breakpoint_list.Breakpoints())
+ {
+ if (breakpoint_sp->IsInternal())
+ continue;
+
+ BreakpointSP new_bp (new Breakpoint (*this, *breakpoint_sp.get()));
+ AddBreakpoint (new_bp, false);
+ }
+}
+
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@@ -330,7 +351,7 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
BreakpointSP
Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
{
- SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
+ SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this()));
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false);
}
@@ -430,7 +451,7 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule)
else
{
if (m_search_filter_sp.get() == NULL)
- m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
+ m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
return filter_sp;
@@ -449,7 +470,7 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules)
else
{
if (m_search_filter_sp.get() == NULL)
- m_search_filter_sp.reset (new SearchFilterForNonModuleSpecificSearches (shared_from_this()));
+ m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
return filter_sp;
@@ -510,29 +531,35 @@ Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resol
{
bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware, resolve_indirect_symbols));
resolver_sp->SetBreakpoint (bp_sp.get());
+ AddBreakpoint (bp_sp, internal);
+ }
+ return bp_sp;
+}
- if (internal)
- m_internal_breakpoint_list.Add (bp_sp, false);
- else
- m_breakpoint_list.Add (bp_sp, true);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- {
- StreamString s;
- bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
- log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData());
- }
+void
+Target::AddBreakpoint (lldb::BreakpointSP bp_sp, bool internal)
+{
+ if (!bp_sp)
+ return;
+ if (internal)
+ m_internal_breakpoint_list.Add (bp_sp, false);
+ else
+ m_breakpoint_list.Add (bp_sp, true);
- bp_sp->ResolveBreakpoint();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ {
+ StreamString s;
+ bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, bp_sp->IsInternal() ? "yes" : "no", s.GetData());
}
-
- if (!internal && bp_sp)
+
+ bp_sp->ResolveBreakpoint();
+
+ if (!internal)
{
m_last_created_breakpoint = bp_sp;
}
-
- return bp_sp;
}
bool
@@ -1214,6 +1241,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
{
if (m_valid && module_list.GetSize())
{
+ UnloadModuleSections (module_list);
m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
@@ -1221,7 +1249,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
}
bool
-Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_file_spec)
+Target::ModuleIsExcludedForUnconstrainedSearches (const FileSpec &module_file_spec)
{
if (GetBreakpointsConsultPlatformAvoidList())
{
@@ -1235,7 +1263,7 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil
{
for (size_t i = 0; i < num_modules; i++)
{
- if (!ModuleIsExcludedForNonModuleSpecificSearches (matchingModules.GetModuleAtIndex(i)))
+ if (!ModuleIsExcludedForUnconstrainedSearches (matchingModules.GetModuleAtIndex(i)))
return false;
}
return true;
@@ -1245,12 +1273,12 @@ Target::ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_fil
}
bool
-Target::ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp)
+Target::ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp)
{
if (GetBreakpointsConsultPlatformAvoidList())
{
if (m_platform_sp)
- return m_platform_sp->ModuleIsExcludedForNonModuleSpecificSearches (*this, module_sp);
+ return m_platform_sp->ModuleIsExcludedForUnconstrainedSearches (*this, module_sp);
}
return false;
}
@@ -1355,9 +1383,9 @@ Target::ReadMemory (const Address& addr,
ModuleSP addr_module_sp (resolved_addr.GetModule());
if (addr_module_sp && addr_module_sp->GetFileSpec())
error.SetErrorStringWithFormat("%s[0x%" PRIx64 "] can't be resolved, %s in not currently loaded",
- addr_module_sp->GetFileSpec().GetFilename().AsCString(),
+ addr_module_sp->GetFileSpec().GetFilename().AsCString("<Unknown>"),
resolved_addr.GetFileAddress(),
- addr_module_sp->GetFileSpec().GetFilename().AsCString());
+ addr_module_sp->GetFileSpec().GetFilename().AsCString("<Unknonw>"));
else
error.SetErrorStringWithFormat("0x%" PRIx64 " can't be resolved", resolved_addr.GetFileAddress());
}
@@ -1436,7 +1464,12 @@ Target::ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_le
Error error;
addr_t curr_addr = addr.GetLoadAddress(this);
Address address(addr);
+
+ // We could call m_process_sp->GetMemoryCacheLineSize() but I don't
+ // think this really needs to be tied to the memory cache subsystem's
+ // cache line size, so leave this as a fixed constant.
const size_t cache_line_size = 512;
+
size_t bytes_left = dst_max_len - 1;
char *curr_dst = dst;
@@ -2006,6 +2039,22 @@ Target::GetSourceManager ()
return *m_source_manager_ap;
}
+ClangModulesDeclVendor *
+Target::GetClangModulesDeclVendor ()
+{
+ static Mutex s_clang_modules_decl_vendor_mutex; // If this is contended we can make it per-target
+
+ {
+ Mutex::Locker clang_modules_decl_vendor_locker(s_clang_modules_decl_vendor_mutex);
+
+ if (!m_clang_modules_decl_vendor_ap)
+ {
+ m_clang_modules_decl_vendor_ap.reset(ClangModulesDeclVendor::Create(*this));
+ }
+ }
+
+ return m_clang_modules_decl_vendor_ap.get();
+}
Target::StopHookSP
Target::CreateStopHook ()
@@ -2173,18 +2222,17 @@ Target::RunStopHooks ()
if (print_thread_header)
result.AppendMessageWithFormat("-- Thread %d\n", exc_ctx_with_reasons[i].GetThreadPtr()->GetIndexID());
-
- bool stop_on_continue = true;
- bool stop_on_error = true;
- bool echo_commands = false;
- bool print_results = true;
- GetDebugger().GetCommandInterpreter().HandleCommands (cur_hook_sp->GetCommands(),
- &exc_ctx_with_reasons[i],
- stop_on_continue,
- stop_on_error,
- echo_commands,
- print_results,
- eLazyBoolNo,
+
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue (true);
+ options.SetStopOnError (true);
+ options.SetEchoCommands (false);
+ options.SetPrintResults (true);
+ options.SetAddToHistory (false);
+
+ GetDebugger().GetCommandInterpreter().HandleCommands (cur_hook_sp->GetCommands(),
+ &exc_ctx_with_reasons[i],
+ options,
result);
// If the command started the target going again, we should bag out of
@@ -2279,6 +2327,12 @@ Target::ResolveLoadAddress (addr_t load_addr, Address &so_addr, uint32_t stop_id
}
bool
+Target::ResolveFileAddress (lldb::addr_t file_addr, Address &resolved_addr)
+{
+ return m_images.ResolveFileAddress(file_addr, resolved_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);
@@ -2297,6 +2351,40 @@ Target::SetSectionLoadAddress (const SectionSP &section_sp, addr_t new_section_l
}
+size_t
+Target::UnloadModuleSections (const ModuleList &module_list)
+{
+ size_t section_unload_count = 0;
+ size_t num_modules = module_list.GetSize();
+ for (size_t i=0; i<num_modules; ++i)
+ {
+ section_unload_count += UnloadModuleSections (module_list.GetModuleAtIndex(i));
+ }
+ return section_unload_count;
+}
+
+size_t
+Target::UnloadModuleSections (const lldb::ModuleSP &module_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();
+ SectionList *sections = module_sp->GetSectionList();
+ size_t section_unload_count = 0;
+ if (sections)
+ {
+ const uint32_t num_sections = sections->GetNumSections(0);
+ for (uint32_t i = 0; i < num_sections; ++i)
+ {
+ section_unload_count += m_section_load_history.SetSectionUnloaded(stop_id, sections->GetSectionAtIndex(i));
+ }
+ }
+ return section_unload_count;
+}
+
bool
Target::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
@@ -2329,10 +2417,14 @@ Target::ClearAllLoadedSections ()
Error
-Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
+Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
{
Error error;
-
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
+
+ if (log)
+ log->Printf ("Target::%s() called for %s", __FUNCTION__, launch_info.GetExecutableFile().GetPath().c_str ());
+
StateType state = eStateInvalid;
// Scope to temporarily get the process state in case someone has manually
@@ -2342,7 +2434,16 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
ProcessSP process_sp (GetProcessSP());
if (process_sp)
+ {
state = process_sp->GetState();
+ if (log)
+ log->Printf ("Target::%s the process exists, and its current state is %s", __FUNCTION__, StateAsCString (state));
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Target::%s the process instance doesn't currently exist.", __FUNCTION__);
+ }
}
launch_info.GetFlags().Set (eLaunchFlagDebug);
@@ -2358,6 +2459,13 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
// 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;
+ if (log)
+ log->Printf ("Target::%s have platform=%s, platform_sp->IsHost()=%s, default_to_use_pty=%s",
+ __FUNCTION__,
+ platform_sp ? "true" : "false",
+ platform_sp ? (platform_sp->IsHost () ? "true" : "false") : "n/a",
+ default_to_use_pty ? "true" : "false");
+
launch_info.FinalizeFileActions (this, default_to_use_pty);
if (state == eStateConnected)
@@ -2375,14 +2483,19 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
// If we're not already connected to the process, and if we have a platform that can launch a process for debugging, go ahead and do that here.
if (state != eStateConnected && platform_sp && platform_sp->CanDebugProcess ())
{
+ if (log)
+ log->Printf ("Target::%s asking the platform to debug the process", __FUNCTION__);
+
m_process_sp = GetPlatform()->DebugProcess (launch_info,
debugger,
this,
- listener,
error);
}
else
{
+ if (log)
+ log->Printf ("Target::%s the platform doesn't know how to debug a process, getting a process plugin to do this for us.", __FUNCTION__);
+
if (state == eStateConnected)
{
assert(m_process_sp);
@@ -2391,7 +2504,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
{
// Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess (listener, plugin_name, NULL);
+ CreateProcess (launch_info.GetListenerForProcess(debugger), plugin_name, NULL);
}
// Since we didn't have a platform launch the process, launch it here.
@@ -2411,8 +2524,8 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
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());
+
+ StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get(), NULL);
if (state == eStateStopped)
{
@@ -2430,7 +2543,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
if (synchronous_execution)
{
- state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get());
+ state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get(), stream);
const bool must_be_alive = false; // eStateExited is ok, so this must be false
if (!StateIsStoppedState(state, must_be_alive))
{
@@ -2447,7 +2560,7 @@ Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
}
else if (state == eStateExited)
{
- bool with_shell = launch_info.GetShell();
+ bool with_shell = !!launch_info.GetShell();
const int exit_status = m_process_sp->GetExitStatus();
const char *exit_desc = m_process_sp->GetExitDescription();
#define LAUNCH_SHELL_MESSAGE "\n'r' and 'run' are aliases that default to launching through a shell.\nTry launching without going through a shell by using 'process launch'."
@@ -2632,7 +2745,7 @@ g_properties[] =
{
{ "default-arch" , OptionValue::eTypeArch , true , 0 , NULL, NULL, "Default architecture to choose, when there's a choice." },
{ "expr-prefix" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "Path to a file containing expressions to be prepended to all expressions." },
- { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eNoDynamicValues , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." },
+ { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eDynamicDontRunTarget , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." },
{ "enable-synthetic-value" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Should synthetic values be used by default whenever available." },
{ "skip-prologue" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Skip function prologues when setting breakpoints by name." },
{ "source-map" , OptionValue::eTypePathMap , false, 0 , NULL, NULL, "Source path remappings used to track the change of location between a source file when built, and "
@@ -2656,12 +2769,13 @@ g_properties[] =
{ "detach-on-error" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "debugserver will detach (rather than killing) a process if it loses connection with lldb." },
{ "disable-aslr" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Disable Address Space Layout Randomization (ASLR)" },
{ "disable-stdio" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Disable stdin/stdout for process (e.g. for a GUI application)" },
- { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsHeaders , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. "
+ { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsAlways , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. "
"Breakpoint locations can end up being inlined by the compiler, so that a compile unit 'a.c' might contain an inlined function from another source file. "
"Usually this is limitted to breakpoint locations from inlined functions from header or other include files, or more accurately non-implementation source files. "
"Sometimes code might #include implementation files and cause inlined breakpoint locations in inlined implementation files. "
- "Always checking for inlined breakpoint locations can be expensive (memory and time), so we try to minimize the "
- "times we look for inlined locations. This setting allows you to control exactly which strategy is used when settings "
+ "Always checking for inlined breakpoint locations can be expensive (memory and time), so if you have a project with many headers "
+ "and find that setting breakpoints is slow, then you can change this setting to headers. "
+ "This setting allows you to control exactly which strategy is used when setting "
"file and line breakpoints." },
// FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet.
{ "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." },