diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/Target.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Target/Target.cpp | 218 |
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 §ion_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 §ion_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 §ion_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." }, |