diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -817,6 +817,12 @@ void ReportErrorIfModifyDetected(const char *format, ...) __attribute__((format(printf, 2, 3))); + void ReportWarningOptimization(llvm::Optional debugger_id); + + void + ReportWarningUnsupportedLanguage(lldb::LanguageType language, + llvm::Optional debugger_id); + // Return true if the file backing this module has changed since the module // was originally created since we saved the initial file modification time // when the module first gets created. @@ -1053,6 +1059,9 @@ /// time for the symbol tables can be aggregated here. StatsDuration m_symtab_index_time; + std::once_flag m_optimization_warning; + std::once_flag m_language_warning; + /// Resolve a file or load virtual address. /// /// Tries to resolve \a vm_addr as a file address (if \a diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -365,9 +365,6 @@ eBroadcastInternalStateControlResume = (1 << 2) }; - /// Process warning types. - enum Warnings { eWarningsOptimization = 1, eWarningsUnsupportedLanguage = 2 }; - typedef Range LoadRange; // We use a read/write lock to allow on or more clients to access the process // state while the process is stopped (reader). We lock the write lock to @@ -2637,35 +2634,6 @@ // Called internally void CompleteAttach(); - /// Print a user-visible warning one time per Process - /// - /// A facility for printing a warning to the user once per repeat_key. - /// - /// warning_type is from the Process::Warnings enums. repeat_key is a - /// pointer value that will be used to ensure that the warning message is - /// not printed multiple times. For instance, with a warning about a - /// function being optimized, you can pass the CompileUnit pointer to have - /// the warning issued for only the first function in a CU, or the Function - /// pointer to have it issued once for every function, or a Module pointer - /// to have it issued once per Module. - /// - /// Classes outside Process should call a specific PrintWarning method so - /// that the warning strings are all centralized in Process, instead of - /// calling PrintWarning() directly. - /// - /// \param [in] warning_type - /// One of the types defined in Process::Warnings. - /// - /// \param [in] repeat_key - /// A pointer value used to ensure that the warning is only printed once. - /// May be nullptr, indicating that the warning is printed unconditionally - /// every time. - /// - /// \param [in] fmt - /// printf style format string - void PrintWarning(uint64_t warning_type, const void *repeat_key, - const char *fmt, ...) __attribute__((format(printf, 4, 5))); - // NextEventAction provides a way to register an action on the next event // that is delivered to this process. There is currently only one next event // action allowed in the process at one time. If a new "NextEventAction" is @@ -2830,8 +2798,6 @@ // Type definitions typedef std::map LanguageRuntimeCollection; - typedef std::unordered_set WarningsPointerSet; - typedef std::map WarningsCollection; struct PreResumeCallbackAndBaton { bool (*callback)(void *); @@ -2961,11 +2927,9 @@ /// ShouldBroadcastEvent. std::map m_resolved_indirect_addresses; bool m_destroy_in_process; - bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, - // don't support the ability to modify - // the stack. - WarningsCollection m_warnings_issued; // A set of object pointers which have - // already had warnings printed + bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, + // don't support the ability to modify + // the stack. std::mutex m_run_thread_plan_lock; StructuredDataPluginMap m_structured_data_plugin_map; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1126,6 +1126,31 @@ return m_file_has_changed; } +void Module::ReportWarningOptimization( + llvm::Optional debugger_id) { + ConstString file_name = GetFileSpec().GetFilename(); + if (file_name.IsEmpty()) + return; + + StreamString ss; + ss << file_name.GetStringRef() + << " was compiled with optimization - stepping may behave " + "oddly; variables may not be available."; + Debugger::ReportWarning(std::string(ss.GetString()), debugger_id, + &m_optimization_warning); +} + +void Module::ReportWarningUnsupportedLanguage( + LanguageType language, llvm::Optional debugger_id) { + StreamString ss; + ss << "This version of LLDB has no plugin for the language \"" + << Language::GetNameForLanguageType(language) + << "\". " + "Inspection of frame variables will be limited."; + Debugger::ReportWarning(std::string(ss.GetString()), debugger_id, + &m_language_warning); +} + void Module::ReportErrorIfModifyDetected(const char *format, ...) { if (!m_first_file_changed_log) { if (FileHasChanged()) { diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -436,8 +436,8 @@ m_private_run_lock(), m_finalizing(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_interpret_function_calls(false), m_warnings_issued(), - m_run_thread_plan_lock(), m_can_jit(eCanJITDontKnow) { + m_can_interpret_function_calls(false), m_run_thread_plan_lock(), + m_can_jit(eCanJITDontKnow) { CheckInWithManager(); Log *log = GetLog(LLDBLog::Object); @@ -5697,48 +5697,12 @@ } } -void Process::PrintWarning(uint64_t warning_type, const void *repeat_key, - const char *fmt, ...) { - bool print_warning = true; - - StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); - if (!stream_sp) - return; - - if (repeat_key != nullptr) { - WarningsCollection::iterator it = m_warnings_issued.find(warning_type); - if (it == m_warnings_issued.end()) { - m_warnings_issued[warning_type] = WarningsPointerSet(); - m_warnings_issued[warning_type].insert(repeat_key); - } else { - if (it->second.find(repeat_key) != it->second.end()) { - print_warning = false; - } else { - it->second.insert(repeat_key); - } - } - } - - if (print_warning) { - va_list args; - va_start(args, fmt); - stream_sp->PrintfVarArg(fmt, args); - va_end(args); - } -} - void Process::PrintWarningOptimization(const SymbolContext &sc) { if (!GetWarningsOptimization()) return; - if (!sc.module_sp) + if (!sc.module_sp || !sc.function || !sc.function->GetIsOptimized()) return; - if (!sc.module_sp->GetFileSpec().GetFilename().IsEmpty() && sc.function && - sc.function->GetIsOptimized()) { - PrintWarning(Process::Warnings::eWarningsOptimization, sc.module_sp.get(), - "%s was compiled with optimization - stepping may behave " - "oddly; variables may not be available.\n", - sc.module_sp->GetFileSpec().GetFilename().GetCString()); - } + sc.module_sp->ReportWarningOptimization(GetTarget().GetDebugger().GetID()); } void Process::PrintWarningUnsupportedLanguage(const SymbolContext &sc) { @@ -5751,13 +5715,10 @@ return; LanguageSet plugins = PluginManager::GetAllTypeSystemSupportedLanguagesForTypes(); - if (!plugins[language]) { - PrintWarning(Process::Warnings::eWarningsUnsupportedLanguage, - sc.module_sp.get(), - "This version of LLDB has no plugin for the language \"%s\". " - "Inspection of frame variables will be limited.\n", - Language::GetNameForLanguageType(language)); - } + if (plugins[language]) + return; + sc.module_sp->ReportWarningUnsupportedLanguage( + language, GetTarget().GetDebugger().GetID()); } bool Process::GetProcessInfo(ProcessInstanceInfo &info) { diff --git a/lldb/test/Shell/Process/Optimization.test b/lldb/test/Shell/Process/Optimization.test --- a/lldb/test/Shell/Process/Optimization.test +++ b/lldb/test/Shell/Process/Optimization.test @@ -1,6 +1,6 @@ Test warnings. REQUIRES: shell, system-darwin RUN: %clang_host -O3 %S/Inputs/true.c -std=c99 -g -o %t.exe -RUN: %lldb -o "b main" -o r -o q -b %t.exe | FileCheck %s +RUN: %lldb -o "b main" -o r -o q -b %t.exe 2>&1 | FileCheck %s CHECK: compiled with optimization diff --git a/lldb/test/Shell/Process/UnsupportedLanguage.test b/lldb/test/Shell/Process/UnsupportedLanguage.test --- a/lldb/test/Shell/Process/UnsupportedLanguage.test +++ b/lldb/test/Shell/Process/UnsupportedLanguage.test @@ -3,6 +3,6 @@ RUN: %clang_host %S/Inputs/true.c -std=c99 -g -c -S -emit-llvm -o - \ RUN: | sed -e 's/DW_LANG_C99/DW_LANG_Mips_Assembler/g' >%t.ll RUN: %clang_host %t.ll -g -o %t.exe -RUN: %lldb -o "b main" -o r -o q -b %t.exe | FileCheck %s +RUN: %lldb -o "b main" -o r -o q -b %t.exe 2>&1 | FileCheck %s CHECK: This version of LLDB has no plugin for the language "assembler"