llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: satyanarayana reddy janga (satyajanga)

<details>
<summary>Changes</summary>

Depends on #<!-- -->218030. The standalone-line-table implementation is the 
second commit in this stack.

## Summary
- recognize and parse standalone DWARF `.debug_line` sections when 
`.debug_info` is absent
- create LLDB compile units directly from line-table prologues without creating 
fake DWARF units
- build line tables and address ranges for address-to-source and 
source-to-address lookup
- accept the recoverable four-byte DWARF v2 prologue padding present in the 
CUDA images while rejecting unusable tables

## Testing
- added a one-object SBAPI test for `.debug_line` + `.symtab` without 
`.debug_info`
- verified that test fails on unmodified LLDB (`GetNumCompileUnits()` returns 
0) and passes with this stack
- focused standalone-line shell test passed
- `SymbolFileDWARFTests`: 56/56 passed
- `SymbolTests`: 126/126 passed
- rebuilt and tested the exact stack against current `upstream/main`
- NVIDIA validation: the CUDA core resolves the selected frame to CUDA source 
line 184 and GPU address `0x7f4b397cbaf0` to `vecn.cuh:111`


---

Patch is 29.21 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/217932.diff


8 Files Affected:

- (modified) lldb/include/lldb/Symbol/SymbolFile.h (+5-2) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+201-34) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+6) 
- (modified) lldb/source/Symbol/SymbolFile.cpp (+10-1) 
- (added) 
lldb/test/API/python_api/symbol-context/standalone-debug-line/TestStandaloneDebugLine.py
 (+63) 
- (added) lldb/test/API/python_api/symbol-context/standalone-debug-line/main.s 
(+14) 
- (added) lldb/test/Shell/SymbolFile/DWARF/x86/standalone-debug-line.s (+160) 
- (modified) lldb/unittests/Symbol/LineTableTest.cpp (+36-10) 


``````````diff
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h 
b/lldb/include/lldb/Symbol/SymbolFile.h
index ae6504c016d7b..0ec2e10cfeaa0 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -95,8 +95,11 @@ class SymbolFile : public PluginInterface {
   /// trying to figure out which symbol file plug-in will get used
   /// for a given object file. The plug-in that responds with the
   /// best mix of "SymbolFile::Abilities" bits set, will get chosen to
-  /// be the symbol file parser. This allows each plug-in to check for
-  /// sections that contain data a symbol file plug-in would need. For
+  /// be the symbol file parser. Plug-ins that provide detailed debug
+  /// information such as line tables, blocks, local variables, or types are
+  /// preferred over plug-ins that provide only information obtainable from an
+  /// object file's symbol table. This allows each plug-in to check for 
sections
+  /// that contain data a symbol file plug-in would need. For
   /// example the DWARF plug-in requires DWARF sections in a file that
   /// contain debug information. If the DWARF plug-in doesn't find
   /// these sections, it won't respond with many ability bits set, and
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 81cd4444161f7..080c158f325e2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -308,6 +308,68 @@ static void ParseSupportFilesFromPrologue(
   }
 }
 
+struct lldb_private::plugin::dwarf::StandaloneDWARFLineTableInfo {
+  std::vector<llvm::DWARFDebugLine::LineTable> line_tables;
+  llvm::once_flag aranges_once_flag;
+  DWARFDebugAranges aranges;
+
+  const llvm::DWARFDebugLine::LineTable *GetLineTable(uint32_t cu_idx) const;
+
+  const DWARFDebugAranges &GetAranges(lldb::addr_t first_code_address);
+};
+
+static std::unique_ptr<LineTable>
+ConvertLineTable(CompileUnit &comp_unit,
+                 const llvm::DWARFDebugLine::LineTable &line_table,
+                 lldb::addr_t first_code_address) {
+  // FIXME: Rather than parsing the whole line table and then copying it over
+  // into LLDB, we should explore using a callback to populate the line table
+  // while we parse to reduce memory usage.
+  std::vector<LineTable::Sequence> sequences;
+  // The Sequences view contains only valid line sequences. Don't iterate over
+  // the Rows directly.
+  for (const llvm::DWARFDebugLine::Sequence &seq : line_table.Sequences) {
+    // Ignore line sequences that do not start after the first code address.
+    // All addresses generated in a sequence are incremental so we only need
+    // to check the first one of the sequence.
+    if (seq.LowPC < first_code_address)
+      continue;
+    LineTable::Sequence sequence;
+    for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
+      const llvm::DWARFDebugLine::Row &row = line_table.Rows[idx];
+      LineTable::AppendLineEntryToSequence(
+          sequence, row.Address.Address, row.Line, row.Column, row.File,
+          row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
+          row.EndSequence);
+    }
+    sequences.push_back(std::move(sequence));
+  }
+
+  return std::make_unique<LineTable>(&comp_unit, std::move(sequences));
+}
+
+const llvm::DWARFDebugLine::LineTable *
+StandaloneDWARFLineTableInfo::GetLineTable(uint32_t cu_idx) const {
+  if (cu_idx >= line_tables.size())
+    return nullptr;
+  return &line_tables[cu_idx];
+}
+
+const DWARFDebugAranges &
+StandaloneDWARFLineTableInfo::GetAranges(lldb::addr_t first_code_address) {
+  llvm::call_once(aranges_once_flag, [&] {
+    for (uint32_t cu_idx = 0; cu_idx < line_tables.size(); ++cu_idx) {
+      for (const llvm::DWARFDebugLine::Sequence &seq :
+           line_tables[cu_idx].Sequences) {
+        if (seq.isValid() && seq.LowPC >= first_code_address)
+          aranges.AppendRange(cu_idx, seq.LowPC, seq.HighPC);
+      }
+    }
+    aranges.Sort(/*minimize=*/true);
+  });
+  return aranges;
+}
+
 void SymbolFileDWARF::Initialize() {
   LogChannelDWARF::Initialize();
   PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -628,6 +690,11 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
     if (section)
       section_list = &section->GetChildren();
 
+    section =
+        section_list->FindSectionByType(eSectionTypeDWARFDebugLine, 
true).get();
+    if (section)
+      debug_line_file_size = section->GetFileSize();
+
     section =
         section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, 
true).get();
     if (section != nullptr) {
@@ -651,11 +718,6 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
         return 0;
       }
 
-      section =
-          section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true)
-              .get();
-      if (section)
-        debug_line_file_size = section->GetFileSize();
     } else {
       llvm::StringRef symfile_dir = m_objfile_sp->GetFileSpec().GetDirectory();
       if (symfile_dir.contains_insensitive(".dsym")) {
@@ -684,12 +746,17 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
       return 0;
     }
 
-    if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
+    if (debug_abbrev_file_size > 0 && debug_info_file_size > 0) {
       abilities |= CompileUnits | Functions | Blocks | GlobalVariables |
                    LocalVariables | VariableTypes;
 
-    if (debug_line_file_size > 0)
-      abilities |= LineTables;
+      if (debug_line_file_size > 0)
+        abilities |= LineTables;
+    } else if (debug_line_file_size > 0 &&
+               !GetStandaloneLineTableInfo().line_tables.empty())
+      // A standalone line table still supplies enough information to create
+      // compile units, even though there are no DIEs backing them.
+      abilities |= CompileUnits | LineTables;
   }
   return abilities;
 }
@@ -741,9 +808,59 @@ DWARFDebugInfo &SymbolFileDWARF::DebugInfo() {
   return *m_info;
 }
 
+StandaloneDWARFLineTableInfo &SymbolFileDWARF::GetStandaloneLineTableInfo() {
+  llvm::call_once(m_standalone_line_table_once_flag, [&] {
+    auto info = std::make_unique<StandaloneDWARFLineTableInfo>();
+
+    // A DWARFUnit implies the presence of .debug_info. Standalone line tables
+    // deliberately bypass DWARFUnit creation and directly synthesize LLDB
+    // compile units instead.
+    if (m_context.getOrLoadDebugInfoData().GetByteSize() != 0) {
+      m_standalone_line_table_info = std::move(info);
+      return;
+    }
+
+    llvm::DWARFDataExtractor line_data =
+        m_context.getOrLoadLineData().GetAsLLVMDWARF();
+    if (line_data.getData().empty()) {
+      m_standalone_line_table_info = std::move(info);
+      return;
+    }
+
+    llvm::DWARFContext &context = m_context.GetAsLLVM();
+    llvm::DWARFDebugLine::SectionParser parser(line_data, context,
+                                               context.normal_units());
+    Log *log = GetLog(DWARFLog::DebugInfo);
+    while (!parser.done()) {
+      bool valid = true;
+      auto recoverable = [&](llvm::Error error) {
+        LLDB_LOG_ERROR(log, std::move(error),
+                       "SymbolFileDWARF failed to parse standalone line "
+                       "table: {0}");
+      };
+      auto unrecoverable = [&](llvm::Error error) {
+        valid = false;
+        LLDB_LOG_ERROR(log, std::move(error),
+                       "SymbolFileDWARF failed to parse standalone line "
+                       "table: {0}");
+      };
+      llvm::DWARFDebugLine::LineTable line_table =
+          parser.parseNext(recoverable, unrecoverable);
+      if (valid && SupportedVersion(line_table.Prologue.getVersion()) &&
+          !line_table.Prologue.FileNames.empty())
+        info->line_tables.push_back(std::move(line_table));
+    }
+    m_standalone_line_table_info = std::move(info);
+  });
+  return *m_standalone_line_table_info;
+}
+
 DWARFCompileUnit *SymbolFileDWARF::GetDWARFCompileUnit(CompileUnit *comp_unit) 
{
   if (!comp_unit)
     return nullptr;
+  if (m_standalone_line_table_info &&
+      comp_unit->GetUserData() == m_standalone_line_table_info.get())
+    return nullptr;
 
   // The compile unit ID is the index of the DWARF unit.
   DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(comp_unit->GetID());
@@ -888,6 +1005,12 @@ std::optional<uint32_t> 
SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) {
 }
 
 uint32_t SymbolFileDWARF::CalculateNumCompileUnits() {
+  if (!GetDebugMapSymfile()) {
+    StandaloneDWARFLineTableInfo &standalone = GetStandaloneLineTableInfo();
+    if (!standalone.line_tables.empty())
+      return standalone.line_tables.size();
+  }
+
   BuildCuTranslationTable();
   return m_lldb_cu_to_dwarf_unit.empty() ? DebugInfo().GetNumUnits()
                                          : m_lldb_cu_to_dwarf_unit.size();
@@ -895,6 +1018,33 @@ uint32_t SymbolFileDWARF::CalculateNumCompileUnits() {
 
 CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
   ASSERT_MODULE_LOCK(this);
+  StandaloneDWARFLineTableInfo &info = GetStandaloneLineTableInfo();
+  const llvm::DWARFDebugLine::LineTable *line_table =
+      GetDebugMapSymfile() ? nullptr : info.GetLineTable(cu_idx);
+  if (line_table) {
+    SupportFileList support_files;
+    ParseSupportFilesFromPrologue(support_files, m_objfile_sp->GetModule(),
+                                  line_table->Prologue,
+                                  m_objfile_sp->GetFileSpec().GetPathStyle());
+
+    // DWARF v5 guarantees that file index zero names the primary source file.
+    // Earlier versions are one-based and have no explicit primary-file field;
+    // use the first file in the table as the best available fallback.
+    const size_t primary_file_idx =
+        line_table->Prologue.getVersion() < 5 ? 1 : 0;
+    SupportFileNSP primary_file =
+        support_files.GetSupportFileAtIndex(primary_file_idx);
+
+    ModuleSP module_sp = m_objfile_sp->GetModule();
+    if (!module_sp)
+      return {};
+    CompUnitSP cu_sp = std::make_shared<CompileUnit>(
+        module_sp, m_standalone_line_table_info.get(), primary_file, cu_idx,
+        eLanguageTypeUnknown, eLazyBoolNo, std::move(support_files));
+    SetCompileUnitAtIndex(cu_idx, cu_sp);
+    return cu_sp;
+  }
+
   if (std::optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) {
     if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>(
             DebugInfo().GetUnitAtIndex(*dwarf_idx)))
@@ -1239,6 +1389,20 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit 
&comp_unit) {
   if (comp_unit.GetLineTable() != nullptr)
     return true;
 
+  if (m_standalone_line_table_info &&
+      comp_unit.GetUserData() == m_standalone_line_table_info.get()) {
+    const llvm::DWARFDebugLine::LineTable *line_table =
+        m_standalone_line_table_info->GetLineTable(comp_unit.GetID());
+    if (!line_table)
+      return false;
+    if (m_first_code_address == LLDB_INVALID_ADDRESS)
+      InitializeFirstCodeAddress();
+    comp_unit.SetLineTable(
+        ConvertLineTable(comp_unit, *line_table, m_first_code_address)
+            .release());
+    return true;
+  }
+
   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
   if (!dwarf_cu)
     return false;
@@ -1255,32 +1419,8 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit 
&comp_unit) {
   if (!line_table)
     return false;
 
-  // FIXME: Rather than parsing the whole line table and then copying it over
-  // into LLDB, we should explore using a callback to populate the line table
-  // while we parse to reduce memory usage.
-  std::vector<LineTable::Sequence> sequences;
-  // The Sequences view contains only valid line sequences. Don't iterate over
-  // the Rows directly.
-  for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) {
-    // Ignore line sequences that do not start after the first code address.
-    // All addresses generated in a sequence are incremental so we only need
-    // to check the first one of the sequence. Check the comment at the
-    // m_first_code_address declaration for more details on this.
-    if (seq.LowPC < m_first_code_address)
-      continue;
-    LineTable::Sequence sequence;
-    for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
-      const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx];
-      LineTable::AppendLineEntryToSequence(
-          sequence, row.Address.Address, row.Line, row.Column, row.File,
-          row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
-          row.EndSequence);
-    }
-    sequences.push_back(std::move(sequence));
-  }
-
   std::unique_ptr<LineTable> line_table_up =
-      std::make_unique<LineTable>(&comp_unit, std::move(sequences));
+      ConvertLineTable(comp_unit, *line_table, m_first_code_address);
 
   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) {
     // We have an object file that has a line table with addresses that are not
@@ -2151,6 +2291,33 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const 
Address &so_addr,
        eSymbolContextLineEntry | eSymbolContextVariable)) {
     lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
 
+    StandaloneDWARFLineTableInfo &standalone = GetStandaloneLineTableInfo();
+    if (!GetDebugMapSymfile() && !standalone.line_tables.empty()) {
+      if (m_first_code_address == LLDB_INVALID_ADDRESS)
+        InitializeFirstCodeAddress();
+      const DWARFDebugAranges &aranges =
+          standalone.GetAranges(m_first_code_address);
+      const dw_offset_t cu_idx = aranges.FindAddress(file_vm_addr);
+      if (cu_idx == DW_INVALID_OFFSET)
+        return 0;
+
+      CompUnitSP cu_sp = GetCompileUnitAtIndex(cu_idx);
+      sc.comp_unit = cu_sp.get();
+      if (!sc.comp_unit)
+        return 0;
+      resolved |= eSymbolContextCompUnit;
+
+      if (resolve_scope & eSymbolContextLineEntry) {
+        if (LineTable *line_table = sc.comp_unit->GetLineTable()) {
+          Address exe_so_addr(so_addr);
+          if (FixupAddress(exe_so_addr) &&
+              line_table->FindLineEntryByAddress(exe_so_addr, sc.line_entry))
+            resolved |= eSymbolContextLineEntry;
+        }
+      }
+      return resolved;
+    }
+
     DWARFDebugInfo &debug_info = DebugInfo();
     const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges();
     const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr);
@@ -2251,7 +2418,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(
   if (resolve_scope & eSymbolContextCompUnit) {
     for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
          ++cu_idx) {
-      CompileUnit *dc_cu = ParseCompileUnitAtIndex(cu_idx).get();
+      CompileUnit *dc_cu = GetCompileUnitAtIndex(cu_idx).get();
       if (!dc_cu)
         continue;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 9879fc4fe922c..a1f539e0fd890 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -60,6 +60,7 @@ class DWARFTypeUnit;
 class SymbolFileDWARFDebugMap;
 class SymbolFileDWARFDwo;
 class SymbolFileDWARFDwp;
+struct StandaloneDWARFLineTableInfo;
 
 #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1)
 
@@ -516,6 +517,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
   void BuildCuTranslationTable();
   std::optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx);
 
+  StandaloneDWARFLineTableInfo &GetStandaloneLineTableInfo();
+
   void FindDwpSymbolFile();
 
   const SupportFileList *GetTypeUnitSupportFiles(DWARFTypeUnit &tu);
@@ -538,6 +541,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
   llvm::once_flag m_info_once_flag;
   std::unique_ptr<DWARFDebugInfo> m_info;
 
+  llvm::once_flag m_standalone_line_table_once_flag;
+  std::unique_ptr<StandaloneDWARFLineTableInfo> m_standalone_line_table_info;
+
   std::unique_ptr<llvm::DWARFDebugAbbrev> m_abbr;
   std::unique_ptr<GlobalVariableMap> m_global_aranges_up;
 
diff --git a/lldb/source/Symbol/SymbolFile.cpp 
b/lldb/source/Symbol/SymbolFile.cpp
index 0ef139b1d453a..d993e780a04cd 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -23,6 +23,7 @@
 #include "lldb/lldb-private.h"
 
 #include <future>
+#include <utility>
 
 using namespace lldb_private;
 using namespace lldb;
@@ -30,6 +31,13 @@ using namespace lldb;
 char SymbolFile::ID;
 char SymbolFileCommon::ID;
 
+static std::pair<bool, uint32_t> GetSymbolFileRank(uint32_t abilities) {
+  constexpr uint32_t detailed_info =
+      SymbolFile::LineTables | SymbolFile::Blocks | SymbolFile::LocalVariables 
|
+      SymbolFile::VariableTypes;
+  return {static_cast<bool>(abilities & detailed_info), abilities};
+}
+
 void SymbolFile::PreloadSymbols() {
   // No-op for most implementations.
 }
@@ -65,7 +73,8 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFileSP objfile_sp) {
 
       if (curr_symfile_up) {
         const uint32_t sym_file_abilities = curr_symfile_up->GetAbilities();
-        if (sym_file_abilities > best_symfile_abilities) {
+        if (GetSymbolFileRank(sym_file_abilities) >
+            GetSymbolFileRank(best_symfile_abilities)) {
           best_symfile_abilities = sym_file_abilities;
           best_symfile_up.reset(curr_symfile_up.release());
           // If any symbol file parser has all of the abilities, then we should
diff --git 
a/lldb/test/API/python_api/symbol-context/standalone-debug-line/TestStandaloneDebugLine.py
 
b/lldb/test/API/python_api/symbol-context/standalone-debug-line/TestStandaloneDebugLine.py
new file mode 100644
index 0000000000000..13d6db338b019
--- /dev/null
+++ 
b/lldb/test/API/python_api/symbol-context/standalone-debug-line/TestStandaloneDebugLine.py
@@ -0,0 +1,63 @@
+import os
+
+import lldb
+from lldbsuite.test import configuration
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class StandaloneDebugLineTestCase(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessPlatform(["linux"])
+    @skipIfLLVMTargetMissing("X86")
+    def test(self):
+        object_path = self.getBuildArtifact("line.o")
+        self.runBuildCommand(
+            [
+                os.path.join(configuration.llvm_tools_dir, "llvm-mc"),
+                "-triple=x86_64-pc-linux",
+                "-filetype=obj",
+                "-dwarf-version=2",
+                self.getSourcePath("main.s"),
+                "-o",
+                object_path,
+            ]
+        )
+
+        target = self.createTestTarget(object_path)
+
+        # The regular symbol table advertises functions, while the standalone
+        # line table must make SymbolFileDWARF the preferred reader.
+        module = target.GetModuleAtIndex(0)
+        self.assertTrue(module.FindSection(".debug_line").IsValid())
+        self.assertFalse(module.FindSection(".debug_info").IsValid())
+        self.assertFalse(module.FindSection(".debug_abbrev").IsValid())
+        self.assertTrue(module.FindSection(".symtab").IsValid())
+        self.assertEqual(module.GetNumCompileUnits(), 1)
+
+        # An address must resolve to its symbol, synthetic compile unit, and
+        # line entry. It must not manufacture a DWARF function.
+        symbol = module.FindSymbol("foo", lldb.eSymbolTypeCode)
+        self.assertTrue(symbol.IsValid())
+
+        address = symbol.GetStartAddress()
+        self.assertTrue(address.IsValid())
+        self.assertEqual(address.GetSymbol().GetName(), "foo")
+        self.assertFalse(address.GetFunction().IsValid())
+
+        compile_unit = address.GetCompileUnit()
+        self.assertTrue(compile_unit.IsValid())
+        self.assertEqual(compile_unit.GetFileSpec().GetFilename(), 
"standalone.c")
+
+        line_entry = address.GetLineEntry()
+        self.assertTrue(line_entry.IsValid())
+        self.assertEqual(line_entry.GetFileSpec().GetFilename(), 
"standalone.c")
+        self.assertEqual(line_entry.GetLine(), 42)
+        self.assertEqual(line_entry.GetColumn(), 7)
+
+        # Source-to-address lookup must use the same standalone line table.
+        breakpoint = target.BreakpointCreateByLocation("standalone.c", 42)
+        self.assertEqual(breakpoint.GetNumLocations(), 1)
+        breakpoint_address = breakpoint.GetLocationAtIndex(0).GetAddress()
+        self.assertEqual(breakpoint_a...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/217932
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to