Author: Greg Clayton Date: 2024-02-20T18:17:01-08:00 New Revision: 5a45d32b5b42dc4ed4852b0045391a1c2be41b48
URL: https://github.com/llvm/llvm-project/commit/5a45d32b5b42dc4ed4852b0045391a1c2be41b48 DIFF: https://github.com/llvm/llvm-project/commit/5a45d32b5b42dc4ed4852b0045391a1c2be41b48.diff LOG: [lldb] Add more ways to find the .dwp file. (#81067) When using split DWARF we can run into many different ways to store debug info: - lldb loads `<exe>` which contains skeleton DWARF and needs to find `<exe>.dwp` - lldb loads `<exe>` which is stripped but has .gnu_debuglink pointing to `<exe>.debug` with skeleton DWARF and needs to find `<exe>.dwp` - lldb loads `<exe>` which is stripped but has .gnu_debuglink pointing to `<exe>.debug` with skeleton DWARF and needs to find `<exe>.debug.dwp` - lldb loads `<exe>.debug` and needs to find `<exe>.dwp` Previously we only handled the first two cases. This patch adds support for the latter two. Added: Modified: lldb/include/lldb/Utility/FileSpecList.h lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h index 49edc667ddd5b6..6eb3bb9971f13a 100644 --- a/lldb/include/lldb/Utility/FileSpecList.h +++ b/lldb/include/lldb/Utility/FileSpecList.h @@ -238,6 +238,10 @@ class FileSpecList { const_iterator begin() const { return m_files.begin(); } const_iterator end() const { return m_files.end(); } + llvm::iterator_range<const_iterator> files() const { + return llvm::make_range(begin(), end()); + } + protected: collection m_files; ///< A collection of FileSpec objects. }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp index 6b063f3bd88d85..795355b57a06db 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -22,6 +22,7 @@ static constexpr Log::Category g_categories[] = { {{"map"}, {"log insertions of object files into DWARF debug maps"}, DWARFLog::DebugMap}, + {{"split"}, {"log split DWARF related activities"}, DWARFLog::SplitDwarf}, }; static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h index 662aa6757e2ffc..7f254a1162bd10 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -20,6 +20,7 @@ enum class DWARFLog : Log::MaskType { DebugMap = Log::ChannelFlag<2>, Lookups = Log::ChannelFlag<3>, TypeCompletion = Log::ChannelFlag<4>, + SplitDwarf = Log::ChannelFlag<5>, LLVM_MARK_AS_BITMASK_ENUM(TypeCompletion) }; LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 42211b9a21b0e3..84ff4c2565a050 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4349,26 +4349,60 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { + // Create a list of files to try and append .dwp to. + FileSpecList symfiles; + // Append the module's object file path. + const FileSpec module_fspec = m_objfile_sp->GetModule()->GetFileSpec(); + symfiles.Append(module_fspec); + // Append the object file for this SymbolFile only if it is diff erent from + // the module's file path. Our main module could be "a.out", our symbol file + // could be "a.debug" and our ".dwp" file might be "a.debug.dwp" instead of + // "a.out.dwp". + const FileSpec symfile_fspec(m_objfile_sp->GetFileSpec()); + if (symfile_fspec != module_fspec) { + symfiles.Append(symfile_fspec); + } else { + // If we don't have a separate debug info file, then try stripping the + // extension. The main module could be "a.debug" and the .dwp file could + // be "a.dwp" instead of "a.debug.dwp". + ConstString filename_no_ext = + module_fspec.GetFileNameStrippingExtension(); + if (filename_no_ext != module_fspec.GetFilename()) { + FileSpec module_spec_no_ext(module_fspec); + module_spec_no_ext.SetFilename(filename_no_ext); + symfiles.Append(module_spec_no_ext); + } + } + Log *log = GetLog(DWARFLog::SplitDwarf); + FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); ModuleSpec module_spec; module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); - module_spec.GetSymbolFileSpec() = - FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp"); - module_spec.GetUUID() = m_objfile_sp->GetUUID(); - FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); - FileSpec dwp_filespec = - PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); - if (FileSystem::Instance().Exists(dwp_filespec)) { - DataBufferSP dwp_file_data_sp; - lldb::offset_t dwp_file_data_offset = 0; - ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( - GetObjectFile()->GetModule(), &dwp_filespec, 0, - FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp, - dwp_file_data_offset); - if (!dwp_obj_file) - return; - m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>( - *this, dwp_obj_file, DIERef::k_file_index_mask); + for (const auto &symfile : symfiles.files()) { + module_spec.GetSymbolFileSpec() = + FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle()); + LLDB_LOG(log, "Searching for DWP using: \"{0}\"", + module_spec.GetSymbolFileSpec()); + FileSpec dwp_filespec = + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); + if (FileSystem::Instance().Exists(dwp_filespec)) { + LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec); + DataBufferSP dwp_file_data_sp; + lldb::offset_t dwp_file_data_offset = 0; + ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( + GetObjectFile()->GetModule(), &dwp_filespec, 0, + FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp, + dwp_file_data_offset); + if (dwp_obj_file) { + m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>( + *this, dwp_obj_file, DIERef::k_file_index_mask); + break; + } + } + } + if (!m_dwp_symfile) { + LLDB_LOG(log, "Unable to locate for DWP file for: \"{0}\"", + m_objfile_sp->GetModule()->GetFileSpec()); } }); return m_dwp_symfile; diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp index a47209931c3840..9a8149065b6e58 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp @@ -1,12 +1,16 @@ // REQUIRES: lld +// Now test with DWARF5 // RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.dwarf5.o // RUN: ld.lld %t.dwarf5.o -o %t.dwarf5 // RUN: llvm-dwp %t.dwarf5.dwo -o %t.dwarf5.dwp // RUN: rm %t.dwarf5.dwo // RUN: llvm-objcopy --only-keep-debug %t.dwarf5 %t.dwarf5.debug // RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf5.debug %t.dwarf5 -// RUN: %lldb %t.dwarf5 -o "target variable a" -b | FileCheck %s +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "target variable a" \ +// RUN: -b %t.dwarf5 | FileCheck %s // Run one time with the index cache enabled to populate the index cache. When // we populate the index cache we have to parse all of the DWARF debug info @@ -34,6 +38,31 @@ // RUN: -o "statistics dump" \ // RUN: %t.dwarf5 -b | FileCheck %s -check-prefix=CACHED +// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf5.dwp" +// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we load the "%t.dwarf5" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp" +// RUN: mv %t.dwarf5.dwp %t.dwarf5.debug.dwp +// RUN: %lldb %t.dwarf5 -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp" +// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we remove the .dwp file we see an appropriate error. +// RUN: rm %t.dwarf5.debug.dwp +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "b main" \ +// RUN: -b %t.dwarf5 2>&1 | FileCheck %s -check-prefix=NODWP + +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "b main" \ +// RUN: -b %t.dwarf5.debug 2>&1 | FileCheck %s -check-prefix=NODWP + // Now test with DWARF4 // RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-4 -c %s -o %t.dwarf4.o // RUN: ld.lld %t.dwarf4.o -o %t.dwarf4 @@ -41,7 +70,10 @@ // RUN: rm %t.dwarf4.dwo // RUN: llvm-objcopy --only-keep-debug %t.dwarf4 %t.dwarf4.debug // RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf4.debug %t.dwarf4 -// RUN: %lldb %t.dwarf4 -o "target variable a" -b | FileCheck %s +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "target variable a" \ +// RUN: -b %t.dwarf4 | FileCheck %s // Run one time with the index cache enabled to populate the index cache. When // we populate the index cache we have to parse all of the DWARF debug info @@ -69,6 +101,46 @@ // RUN: -o "statistics dump" \ // RUN: %t.dwarf4 -b | FileCheck %s -check-prefix=CACHED +// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf4.dwp" +// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we load the "%t.dwarf4" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp" +// RUN: mv %t.dwarf4.dwp %t.dwarf4.debug.dwp +// RUN: %lldb %t.dwarf4 -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and +// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp" +// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG + +// Make sure that if we remove the .dwp file we see an appropriate error. +// RUN: rm %t.dwarf4.debug.dwp +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "b main" \ +// RUN: -b %t.dwarf4 2>&1 | FileCheck %s -check-prefix=NODWP + +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "b main" \ +// RUN: -b %t.dwarf4.debug 2>&1 | FileCheck %s -check-prefix=NODWP + +// Test if we have a GNU build ID in our main executable and in our debug file, +// and we have a .dwp file that doesn't, that we can still load our .dwp file. +// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.o +// RUN: ld.lld %t.o --build-id=md5 -o %t +// RUN: llvm-dwp %t.dwo -o %t.dwp +// RUN: rm %t.dwo +// RUN: llvm-objcopy --only-keep-debug %t %t.debug +// RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.debug %t +// RUN: %lldb \ +// RUN: -O "log enable dwarf split" \ +// RUN: -o "target variable a" \ +// RUN: -b %t | FileCheck %s + +// CHECK: Searching for DWP using: +// CHECK: Found DWP file: // CHECK: (A) a = (x = 47) // CACHE: script lldb.target.modules[0].FindTypes('::A').GetTypeAtIndex(0) @@ -83,6 +155,16 @@ // CACHED-NEXT: } // CACHED: "totalDebugInfoIndexLoadedFromCache": 1 +// Make sure debug information was loaded by verifying that the +// DEBUG: Breakpoint 1: where = dwp-separate-debug-file.cpp.tmp.dwarf{{[45]}}{{(\.debug)?}}`main + {{[0-9]+}} at dwp-separate-debug-file.cpp:{{[0-9]+}}:{{[0-9]+}}, address = {{0x[0-9a-fA-F]+}} + +// Make sure if we load the stripped binary or the debug info file with no .dwp +// nor any .dwo files that we are not able to fine the .dwp or .dwo files. +// NODWP: Searching for DWP using: +// NODWP: Searching for DWP using: +// NODWP: Unable to locate for DWP file for: +// NODWP: unable to locate separate debug file (dwo, dwp). Debugging will be degraded. + struct A { int x = 47; }; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits