[llvm] da0828b - [lldb] Enable support for DWARF64 format handling (#145645)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 1 06:05:43 PDT 2025


Author: Hemang Gadhavi
Date: 2025-07-01T18:35:40+05:30
New Revision: da0828b1e93c0fb6266225d8e6d41b2d9ef1f346

URL: https://github.com/llvm/llvm-project/commit/da0828b1e93c0fb6266225d8e6d41b2d9ef1f346
DIFF: https://github.com/llvm/llvm-project/commit/da0828b1e93c0fb6266225d8e6d41b2d9ef1f346.diff

LOG: [lldb] Enable support for DWARF64 format handling (#145645)

This PR introduces support for the DWARF64 format, enabling handling of
64-bit DWARF sections as defined by the DWARF specification. The update
includes adjustments to header parsing and modification of form values
to accommodate 64-bit offsets and values.
Also Added the testcase to verify the DWARF64 format.

Added: 
    lldb/unittests/SymbolFile/DWARF/DWARF64UnitTest.cpp

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
    lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
    llvm/docs/ReleaseNotes.md

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index fd3d45cef4c5e..2e98e3c33acaf 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -77,7 +77,9 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
     case DW_FORM_strp:
     case DW_FORM_line_strp:
     case DW_FORM_sec_offset:
-      m_value.uval = data.GetMaxU64(offset_ptr, 4);
+      assert(m_unit);
+      ref_addr_size = m_unit->GetFormParams().getDwarfOffsetByteSize();
+      m_value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
       break;
     case DW_FORM_addrx1:
     case DW_FORM_strx1:
@@ -119,10 +121,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
       break;
     case DW_FORM_ref_addr:
       assert(m_unit);
-      if (m_unit->GetVersion() <= 2)
-        ref_addr_size = m_unit->GetAddressByteSize();
-      else
-        ref_addr_size = 4;
+      ref_addr_size = m_unit->GetFormParams().getRefAddrByteSize();
       m_value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
       break;
     case DW_FORM_indirect:
@@ -165,7 +164,7 @@ static FormSize g_form_sizes[] = {
     {1, 1}, // 0x0b DW_FORM_data1
     {1, 1}, // 0x0c DW_FORM_flag
     {0, 0}, // 0x0d DW_FORM_sdata
-    {1, 4}, // 0x0e DW_FORM_strp
+    {0, 0}, // 0x0e DW_FORM_strp (4 bytes for DWARF32, 8 bytes for DWARF64)
     {0, 0}, // 0x0f DW_FORM_udata
     {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
             // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
@@ -175,7 +174,7 @@ static FormSize g_form_sizes[] = {
     {1, 8},  // 0x14 DW_FORM_ref8
     {0, 0},  // 0x15 DW_FORM_ref_udata
     {0, 0},  // 0x16 DW_FORM_indirect
-    {1, 4},  // 0x17 DW_FORM_sec_offset
+    {0, 0}, // 0x17 DW_FORM_sec_offset (4 bytes for DWARF32,8 bytes for DWARF64)
     {0, 0},  // 0x18 DW_FORM_exprloc
     {1, 0},  // 0x19 DW_FORM_flag_present
     {0, 0},  // 0x1a DW_FORM_strx (ULEB128)
@@ -183,7 +182,7 @@ static FormSize g_form_sizes[] = {
     {1, 4},  // 0x1c DW_FORM_ref_sup4
     {0, 0},  // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
     {1, 16}, // 0x1e DW_FORM_data16
-    {1, 4},  // 0x1f DW_FORM_line_strp
+    {0, 0}, // 0x1f DW_FORM_line_strp (4 bytes for DWARF32, 8 bytes for DWARF64)
     {1, 8},  // 0x20 DW_FORM_ref_sig8
 };
 
@@ -246,13 +245,9 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
     return true;
 
   case DW_FORM_ref_addr:
-    ref_addr_size = 4;
     assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
                   // get this wrong
-    if (unit->GetVersion() <= 2)
-      ref_addr_size = unit->GetAddressByteSize();
-    else
-      ref_addr_size = 4;
+    ref_addr_size = unit->GetFormParams().getRefAddrByteSize();
     *offset_ptr += ref_addr_size;
     return true;
 
@@ -288,7 +283,9 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
     case DW_FORM_sec_offset:
     case DW_FORM_strp:
     case DW_FORM_line_strp:
-      *offset_ptr += 4;
+      assert(unit);
+      ref_addr_size = unit->GetFormParams().getDwarfOffsetByteSize();
+      *offset_ptr += ref_addr_size;
       return true;
 
     // 4 byte values

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index ffd6f1dd52aff..f216ab13e8936 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -1073,20 +1073,7 @@ const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
              : m_dwarf.GetDWARFContext().getOrLoadDebugInfoData();
 }
 
-uint32_t DWARFUnit::GetHeaderByteSize() const {
-  switch (m_header.getUnitType()) {
-  case llvm::dwarf::DW_UT_compile:
-  case llvm::dwarf::DW_UT_partial:
-    return GetVersion() < 5 ? 11 : 12;
-  case llvm::dwarf::DW_UT_skeleton:
-  case llvm::dwarf::DW_UT_split_compile:
-    return 20;
-  case llvm::dwarf::DW_UT_type:
-  case llvm::dwarf::DW_UT_split_type:
-    return GetVersion() < 5 ? 23 : 24;
-  }
-  llvm_unreachable("invalid UnitType.");
-}
+uint32_t DWARFUnit::GetHeaderByteSize() const { return m_header.getSize(); }
 
 std::optional<uint64_t>
 DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const {

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index c05bba36ed74b..f55400eeaa448 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -119,6 +119,9 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
   // Size of the CU data incl. header but without initial length.
   dw_offset_t GetLength() const { return m_header.getLength(); }
   uint16_t GetVersion() const override { return m_header.getVersion(); }
+  const llvm::dwarf::FormParams &GetFormParams() const {
+    return m_header.getFormParams();
+  }
   const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
   dw_offset_t GetAbbrevOffset() const;
   uint8_t GetAddressByteSize() const override {

diff  --git a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
index cf8702209a7c3..eb2e00adba64b 100644
--- a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_unittest(SymbolFileDWARFTests
   DWARFUnitTest.cpp
   SymbolFileDWARFTests.cpp
   XcodeSDKModuleTests.cpp
+  DWARF64UnitTest.cpp
 
   LINK_COMPONENTS
     Support

diff  --git a/lldb/unittests/SymbolFile/DWARF/DWARF64UnitTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARF64UnitTest.cpp
new file mode 100644
index 0000000000000..2303f68674e4c
--- /dev/null
+++ b/lldb/unittests/SymbolFile/DWARF/DWARF64UnitTest.cpp
@@ -0,0 +1,86 @@
+//===-- DWARF64UnitTest.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 "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
+#include "TestingSupport/Symbol/YAMLModuleTester.h"
+
+using namespace lldb_private;
+using namespace lldb_private::dwarf;
+using namespace lldb_private::plugin::dwarf;
+
+TEST(DWARF64UnitTest, DWARF64DebugInfoAndCU) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_PPC64
+DWARF:
+  debug_str:
+    - 'clang version 18.1.8 (clang-18.1.8-1)'
+    - 'main'
+  debug_abbrev:
+    - Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_producer
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_stmt_list 
+              Form:            DW_FORM_sec_offset 
+        - Code:            0x02
+          Tag:             DW_TAG_subprogram 
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name 
+              Form:            DW_FORM_strp
+  debug_info:
+    - Format:          DWARF64
+      Version:         4
+      AbbrOffset:      0x0
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:           0x0
+            - Value:           0x04
+            - Value:           0x0
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0x1
+        - AbbrCode:	   0x0
+)";
+
+  YAMLModuleTester t(yamldata);
+  auto *symbol_file =
+      llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+  DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
+  ASSERT_TRUE(unit);
+  ASSERT_EQ(unit->GetFormParams().Format, DwarfFormat::DWARF64);
+  ASSERT_EQ(unit->GetVersion(), 4);
+  ASSERT_EQ(unit->GetAddressByteSize(), 8);
+
+  DWARFFormValue form_value;
+  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
+  ASSERT_EQ(unit->GetProducer(), eProducerClang);
+  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
+  auto attrs = cu_entry->GetAttributes(unit, DWARFDebugInfoEntry::Recurse::yes);
+  attrs.ExtractFormValueAtIndex(2, form_value); // Validate DW_AT_stmt_list
+  ASSERT_EQ(form_value.Unsigned(), 0UL);
+
+  DWARFDIE cu_die(unit, cu_entry);
+  auto declaration = cu_die.GetFirstChild();
+  ASSERT_TRUE(declaration.IsValid());
+  ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
+}

diff  --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 73ae2ee599640..ae4ce9380d491 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -304,6 +304,7 @@ Changes to LLDB
     stop reason = SIGSEGV: sent by tkill system call (sender pid=649752, uid=2667987)
   ```
 * ELF Cores can now have their siginfo structures inspected using `thread siginfo`.
+* LLDB now supports the `DWARF64` debugging information format.
 
 ### Changes to lldb-dap
 


        


More information about the llvm-commits mailing list