diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -62,6 +62,8 @@ static void MemoryPressureDetected(); + static void SetProgressCallback(ProgressCallback callback, void *baton); + explicit operator bool() const; bool IsValid() const; diff --git a/lldb/include/lldb/Core/Progress.h b/lldb/include/lldb/Core/Progress.h new file mode 100644 --- /dev/null +++ b/lldb/include/lldb/Core/Progress.h @@ -0,0 +1,38 @@ +//===-- Progress.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_CORE_PROGRESS_H +#define LLDB_CORE_PROGRESS_H + +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-types.h" +#include + +namespace lldb_private { +class Progress { +public: + Progress(uint64_t total, const char *format, ...) + __attribute__((format(printf, 3, 4))); + ~Progress(); + void Increment(uint64_t amount = 1); + + static void SetProgressCallback(lldb::ProgressCallback callback, void *baton); + +private: + static void ReportProgress(ConstString message, uint64_t completed, + uint64_t total); + static lldb::ProgressCallback g_callback; + static void *g_callback_baton; + ConstString m_message; + std::atomic m_completed; + const uint64_t m_total; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_PROGRESS_H diff --git a/lldb/include/lldb/lldb-types.h b/lldb/include/lldb/lldb-types.h --- a/lldb/include/lldb/lldb-types.h +++ b/lldb/include/lldb/lldb-types.h @@ -73,6 +73,8 @@ void *baton, const char **argv, lldb_private::CommandReturnObject &result); typedef bool (*ExpressionCancelCallback)(ExpressionEvaluationPhase phase, void *baton); +typedef void (*ProgressCallback)(const char *message, uint64_t completed, + uint64_t total, void *baton); } // namespace lldb #define LLDB_INVALID_PROCESS ((lldb::process_t)-1) diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -38,6 +38,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/DataFormatters/DataVisualization.h" @@ -251,6 +252,10 @@ ModuleList::RemoveOrphanSharedModules(mandatory); } +void SBDebugger::SetProgressCallback(ProgressCallback callback, void *baton) { + Progress::SetProgressCallback(callback, baton); +} + bool SBDebugger::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, IsValid); return this->operator bool(); @@ -808,23 +813,25 @@ // The version of CreateTarget that takes an ArchSpec won't accept an // empty ArchSpec, so when the arch hasn't been specified, we need to // call the target triple version. - error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, filename, - arch_cstr, eLoadDependentsYes, nullptr, target_sp); + error = m_opaque_sp->GetTargetList().CreateTarget( + *m_opaque_sp, filename, arch_cstr, eLoadDependentsYes, nullptr, + target_sp); } else { PlatformSP platform_sp = m_opaque_sp->GetPlatformList() .GetSelectedPlatform(); - ArchSpec arch = Platform::GetAugmentedArchSpec(platform_sp.get(), - arch_cstr); + ArchSpec arch = + Platform::GetAugmentedArchSpec(platform_sp.get(), arch_cstr); if (arch.IsValid()) - error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, filename, - arch, eLoadDependentsYes, platform_sp, target_sp); + error = m_opaque_sp->GetTargetList().CreateTarget( + *m_opaque_sp, filename, arch, eLoadDependentsYes, platform_sp, + target_sp); else error.SetErrorStringWithFormat("invalid arch_cstr: %s", arch_cstr); } if (error.Success()) sb_target.SetSP(target_sp); } - + LLDB_LOGF(log, "SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", " "arch=%s) => SBTarget(%p)", diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt --- a/lldb/source/Core/CMakeLists.txt +++ b/lldb/source/Core/CMakeLists.txt @@ -44,6 +44,7 @@ ModuleList.cpp Opcode.cpp PluginManager.cpp + Progress.cpp RichManglingContext.cpp SearchFilter.cpp Section.cpp diff --git a/lldb/source/Core/Progress.cpp b/lldb/source/Core/Progress.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Core/Progress.cpp @@ -0,0 +1,50 @@ +//===-- Progress.cpp ------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Progress.h" + +#include "lldb/Utility/StreamString.h" + +using namespace lldb; +using namespace lldb_private; + +Progress::Progress(uint64_t total, const char *format, ...) + : m_message(), m_completed(0), m_total(total) { + StreamString message; + va_list args; + va_start(args, format); + message.PrintfVarArg(format, args); + va_end(args); + m_message = ConstString(message.GetString()); + ReportProgress(m_message, 0, m_total); +} + +Progress::~Progress() { + // Make sure to always report progress completed when this object is + // destructed + ReportProgress(m_message, m_total, m_total); +} + +void Progress::Increment(uint64_t amount) { + m_completed += amount; + ReportProgress(m_message, m_completed, m_total); +} + +lldb::ProgressCallback Progress::g_callback = nullptr; +void *Progress::g_callback_baton = nullptr; + +void Progress::SetProgressCallback(ProgressCallback callback, void *baton) { + g_callback = callback; + g_callback_baton = baton; +} + +void Progress::ReportProgress(ConstString message, uint64_t completed, + uint64_t total) { + if (g_callback) + g_callback(message.GetCString(), completed, total, g_callback_baton); +} diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/LZMA.h" @@ -1861,7 +1862,7 @@ // unified section list. if (GetType() != eTypeDebugInfo) unified_section_list = *m_sections_up; - + // If there's a .gnu_debugdata section, we'll try to read the .symtab that's // embedded in there and replace the one in the original object file (if any). // If there's none in the orignal object file, we add it to it. @@ -1879,7 +1880,7 @@ unified_section_list.AddSection(symtab_section_sp); } } - } + } } std::shared_ptr ObjectFileELF::GetGnuDebugDataObjectFile() { @@ -1923,7 +1924,7 @@ ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture(); if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec)) return m_gnu_debug_data_object_file; - + return nullptr; } @@ -2707,6 +2708,9 @@ if (!module_sp) return nullptr; + Progress progress(UINT64_MAX, "Parsing symbol table for %s", + m_file.GetFilename().AsCString("")); + // We always want to use the main object file so we (hopefully) only have one // cached copy of our symtab, dynamic sections, etc. ObjectFile *module_obj_file = module_sp->GetObjectFile(); diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" #include "lldb/Host/Host.h" @@ -1893,9 +1894,9 @@ filename = first_section_sp->GetObjectFile()->GetFileSpec().GetPath(); Host::SystemLog(Host::eSystemLogError, - "error: unable to find section %d for a symbol in %s, corrupt file?\n", - n_sect, - filename.c_str()); + "error: unable to find section %d for a symbol in " + "%s, corrupt file?\n", + n_sect, filename.c_str()); } } if (m_section_infos[n_sect].vm_range.Contains(file_addr)) { @@ -2167,6 +2168,9 @@ if (!module_sp) return 0; + Progress progress(UINT64_MAX, "Parsing symbol table for %s", + m_file.GetFilename().AsCString("")); + struct symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0}; struct linkedit_data_command function_starts_load_command = {0, 0, 0, 0}; struct dyld_info_command dyld_info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" @@ -466,6 +467,10 @@ void SymbolFileDWARF::InitializeObject() { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + Progress progress( + UINT64_MAX, "Indexing DWARF for %s", + GetObjectFile()->GetFileSpec().GetFilename().AsCString("")); + if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) { DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc; LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);