Skip to content

[LLDB][NFC] Added the interface DWARFExpression::Delegate to break dependencies and reduce lldb-server size #131645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 24, 2025

Conversation

slydiman
Copy link
Contributor

This patch addresses the issue #129543.

After this patch DWARFExpression does not call DWARFUnit directly and does not depend on lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp and a lot of clang code.

After this patch the size of lldb-server binary (Linux Aarch64) is reduced from 42MB to 13MB with LLVM 20.0.0
and from 47MB to 17MB with LLVM 21.0.0.

…ies and reduce lldb-server size

This patch addresses the issue llvm#129543.

After this patch DWARFExpression does not call DWARFUnit directly and does not depend on lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp and a lot of clang code.

After this patch the size of lldb-server binary (Linux Aarch64)
is reduced from 42MB to 13MB with LLVM 20.0.0
and from 47MB to 17MB with LLVM 21.0.0.
@slydiman slydiman added the lldb label Mar 17, 2025
@slydiman slydiman requested a review from labath March 17, 2025 17:01
@slydiman slydiman requested a review from JDevlieghere as a code owner March 17, 2025 17:01
@llvmbot
Copy link
Member

llvmbot commented Mar 17, 2025

@llvm/pr-subscribers-lldb

Author: Dmitry Vasilyev (slydiman)

Changes

This patch addresses the issue #129543.

After this patch DWARFExpression does not call DWARFUnit directly and does not depend on lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp and a lot of clang code.

After this patch the size of lldb-server binary (Linux Aarch64) is reduced from 42MB to 13MB with LLVM 20.0.0
and from 47MB to 17MB with LLVM 21.0.0.


Full diff: https://github.com/llvm/llvm-project/pull/131645.diff

5 Files Affected:

  • (modified) lldb/include/lldb/Expression/DWARFExpression.h (+12-11)
  • (modified) lldb/source/Expression/DWARFExpression.cpp (+16-39)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp (+3-3)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (+31-8)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (+39-11)
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 2c1e717ee32eb..cf4098f2acc51 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -23,7 +23,7 @@ namespace lldb_private {
 
 namespace plugin {
 namespace dwarf {
-class DWARFUnit;
+class DWARFUnitInterface;
 } // namespace dwarf
 } // namespace plugin
 
@@ -65,20 +65,20 @@ class DWARFExpression {
   /// \return
   ///     The address specified by the operation, if the operation exists, or
   ///     an llvm::Error otherwise.
-  llvm::Expected<lldb::addr_t>
-  GetLocation_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu) const;
+  llvm::Expected<lldb::addr_t> GetLocation_DW_OP_addr(
+      const plugin::dwarf::DWARFUnitInterface *dwarf_cu) const;
 
-  bool Update_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu,
+  bool Update_DW_OP_addr(const plugin::dwarf::DWARFUnitInterface *dwarf_cu,
                          lldb::addr_t file_addr);
 
   void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
                    uint8_t addr_byte_size);
 
-  bool
-  ContainsThreadLocalStorage(const plugin::dwarf::DWARFUnit *dwarf_cu) const;
+  bool ContainsThreadLocalStorage(
+      const plugin::dwarf::DWARFUnitInterface *dwarf_cu) const;
 
   bool LinkThreadLocalStorage(
-      const plugin::dwarf::DWARFUnit *dwarf_cu,
+      const plugin::dwarf::DWARFUnitInterface *dwarf_cu,
       std::function<lldb::addr_t(lldb::addr_t file_addr)> const
           &link_address_callback);
 
@@ -132,13 +132,14 @@ class DWARFExpression {
   static llvm::Expected<Value>
   Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
            lldb::ModuleSP module_sp, const DataExtractor &opcodes,
-           const plugin::dwarf::DWARFUnit *dwarf_cu,
+           const plugin::dwarf::DWARFUnitInterface *dwarf_cu,
            const lldb::RegisterKind reg_set, const Value *initial_value_ptr,
            const Value *object_address_ptr);
 
-  static bool ParseDWARFLocationList(const plugin::dwarf::DWARFUnit *dwarf_cu,
-                                     const DataExtractor &data,
-                                     DWARFExpressionList *loc_list);
+  static bool
+  ParseDWARFLocationList(const plugin::dwarf::DWARFUnitInterface *dwarf_cu,
+                         const DataExtractor &data,
+                         DWARFExpressionList *loc_list);
 
   bool GetExpressionData(DataExtractor &data) const {
     data = m_data;
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index f48f3ab9307dd..41fbca59db60f 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -133,7 +133,7 @@ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
 static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
                                         const lldb::offset_t data_offset,
                                         const LocationAtom op,
-                                        const DWARFUnit *dwarf_cu) {
+                                        const DWARFUnitInterface *dwarf_cu) {
   lldb::offset_t offset = data_offset;
   switch (op) {
   // Only used in LLVM metadata.
@@ -362,7 +362,8 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
                                // + LEB128
   {
     data.Skip_LEB128(&offset);
-    return DWARFUnit::GetAddressByteSize(dwarf_cu) + offset - data_offset;
+    return DWARFUnitInterface::GetAddressByteSize(dwarf_cu) + offset -
+           data_offset;
   }
 
   case DW_OP_GNU_entry_value:
@@ -393,8 +394,8 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
   return LLDB_INVALID_OFFSET;
 }
 
-llvm::Expected<lldb::addr_t>
-DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
+llvm::Expected<lldb::addr_t> DWARFExpression::GetLocation_DW_OP_addr(
+    const DWARFUnitInterface *dwarf_cu) const {
   lldb::offset_t offset = 0;
   while (m_data.ValidOffset(offset)) {
     const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
@@ -422,7 +423,7 @@ DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
   return LLDB_INVALID_ADDRESS;
 }
 
-bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
+bool DWARFExpression::Update_DW_OP_addr(const DWARFUnitInterface *dwarf_cu,
                                         lldb::addr_t file_addr) {
   lldb::offset_t offset = 0;
   while (m_data.ValidOffset(offset)) {
@@ -481,7 +482,7 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
 }
 
 bool DWARFExpression::ContainsThreadLocalStorage(
-    const DWARFUnit *dwarf_cu) const {
+    const DWARFUnitInterface *dwarf_cu) const {
   lldb::offset_t offset = 0;
   while (m_data.ValidOffset(offset)) {
     const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
@@ -497,7 +498,7 @@ bool DWARFExpression::ContainsThreadLocalStorage(
   return false;
 }
 bool DWARFExpression::LinkThreadLocalStorage(
-    const DWARFUnit *dwarf_cu,
+    const DWARFUnitInterface *dwarf_cu,
     std::function<lldb::addr_t(lldb::addr_t file_addr)> const
         &link_address_callback) {
   const uint32_t addr_byte_size = m_data.GetAddressByteSize();
@@ -783,7 +784,8 @@ enum LocationDescriptionKind {
   /* Composite*/
 };
 /// Adjust value's ValueType according to the kind of location description.
-void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu,
+void UpdateValueTypeFromLocationDescription(Log *log,
+                                            const DWARFUnitInterface *dwarf_cu,
                                             LocationDescriptionKind kind,
                                             Value *value = nullptr) {
   // Note that this function is conflating DWARF expressions with
@@ -875,7 +877,7 @@ static Scalar DerefSizeExtractDataHelper(uint8_t *addr_bytes,
 llvm::Expected<Value> DWARFExpression::Evaluate(
     ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
     lldb::ModuleSP module_sp, const DataExtractor &opcodes,
-    const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_kind,
+    const DWARFUnitInterface *dwarf_cu, const lldb::RegisterKind reg_kind,
     const Value *initial_value_ptr, const Value *object_address_ptr) {
 
   if (opcodes.GetByteSize() == 0)
@@ -2164,35 +2166,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
         if (!bit_size)
           return llvm::createStringError("unspecified architecture");
       } else {
-        // Retrieve the type DIE that the value is being converted to. This
-        // offset is compile unit relative so we need to fix it up.
-        const uint64_t abs_die_offset = die_offset +  dwarf_cu->GetOffset();
-        // FIXME: the constness has annoying ripple effects.
-        DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(abs_die_offset);
-        if (!die)
-          return llvm::createStringError(
-              "cannot resolve DW_OP_convert type DIE");
-        uint64_t encoding =
-            die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
-        bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
-        if (!bit_size)
-          bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
-        if (!bit_size)
-          return llvm::createStringError(
-              "unsupported type size in DW_OP_convert");
-        switch (encoding) {
-        case DW_ATE_signed:
-        case DW_ATE_signed_char:
-          sign = true;
-          break;
-        case DW_ATE_unsigned:
-        case DW_ATE_unsigned_char:
-          sign = false;
-          break;
-        default:
-          return llvm::createStringError(
-              "unsupported encoding in DW_OP_convert");
-        }
+        if (llvm::Error err =
+                const_cast<DWARFUnitInterface *>(dwarf_cu)->GetBitSizeAndSign(
+                    die_offset, bit_size, sign))
+          return err;
       }
       Scalar &top = stack.back().ResolveValue(exe_ctx);
       top.TruncOrExtendTo(bit_size, sign);
@@ -2353,7 +2330,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
 }
 
 bool DWARFExpression::ParseDWARFLocationList(
-    const DWARFUnit *dwarf_cu, const DataExtractor &data,
+    const DWARFUnitInterface *dwarf_cu, const DataExtractor &data,
     DWARFExpressionList *location_list) {
   location_list->Clear();
   std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index fd3d45cef4c5e..c2f4cc6a24af7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -44,8 +44,8 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
     switch (m_form) {
     case DW_FORM_addr:
       assert(m_unit);
-      m_value.uval =
-          data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));
+      m_value.uval = data.GetMaxU64(
+          offset_ptr, DWARFUnitInterface::GetAddressByteSize(m_unit));
       break;
     case DW_FORM_block1:
       m_value.uval = data.GetU8(offset_ptr);
@@ -242,7 +242,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
 
   // Compile unit address sized values
   case DW_FORM_addr:
-    *offset_ptr += DWARFUnit::GetAddressByteSize(unit);
+    *offset_ptr += DWARFUnitInterface::GetAddressByteSize(unit);
     return true;
 
   case DW_FORM_ref_addr:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 1ceeef76f7cc3..168b134b84e2f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -672,6 +672,37 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
   return DWARFDIE(); // Not found
 }
 
+llvm::Error DWARFUnit::GetBitSizeAndSign(uint64_t die_offset,
+                                         uint64_t &bit_size, bool &sign) {
+  // Retrieve the type DIE that the value is being converted to. This
+  // offset is compile unit relative so we need to fix it up.
+  const uint64_t abs_die_offset = die_offset + GetOffset();
+  // FIXME: the constness has annoying ripple effects.
+  DWARFDIE die = GetDIE(abs_die_offset);
+  if (!die)
+    return llvm::createStringError("cannot resolve DW_OP_convert type DIE");
+  uint64_t encoding =
+      die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
+  bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+  if (!bit_size)
+    bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
+  if (!bit_size)
+    return llvm::createStringError("unsupported type size in DW_OP_convert");
+  switch (encoding) {
+  case DW_ATE_signed:
+  case DW_ATE_signed_char:
+    sign = true;
+    break;
+  case DW_ATE_unsigned:
+  case DW_ATE_unsigned_char:
+    sign = false;
+    break;
+  default:
+    return llvm::createStringError("unsupported encoding in DW_OP_convert");
+  }
+  return llvm::Error::success();
+}
+
 llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
   DWARFDebugInfoEntry die;
   if (!die.Extract(GetData(), *this, &die_offset))
@@ -703,14 +734,6 @@ DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
   return *this;
 }
 
-uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
-  if (cu)
-    return cu->GetAddressByteSize();
-  return DWARFUnit::GetDefaultAddressSize();
-}
-
-uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; }
-
 DWARFCompileUnit *DWARFUnit::GetSkeletonUnit() {
   if (m_skeleton_unit.load() == nullptr && IsDWOUnit()) {
     SymbolFileDWARFDwo *dwo =
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index ba142ae86fe0e..8d0bf51208108 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -38,7 +38,34 @@ enum DWARFProducer {
   eProducerOther
 };
 
-class DWARFUnit : public UserID {
+class DWARFUnitInterface {
+public:
+  DWARFUnitInterface() = default;
+  virtual ~DWARFUnitInterface() = default;
+
+  virtual SymbolFileDWARF &GetSymbolFileDWARF() const = 0;
+  virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0;
+  virtual uint16_t GetVersion() const = 0;
+  virtual std::unique_ptr<llvm::DWARFLocationTable>
+  GetLocationTable(const DataExtractor &data) const = 0;
+  virtual dw_addr_t GetBaseAddress() const = 0;
+  virtual uint8_t GetAddressByteSize() const = 0;
+  virtual llvm::Error GetBitSizeAndSign(uint64_t die_offset, uint64_t &bit_size,
+                                        bool &sign) = 0;
+
+  static uint8_t GetAddressByteSize(const DWARFUnitInterface *cu) {
+    if (cu)
+      return cu->GetAddressByteSize();
+    return GetDefaultAddressSize();
+  }
+
+  static uint8_t GetDefaultAddressSize() { return 4; }
+
+  DWARFUnitInterface(const DWARFUnitInterface &) = delete;
+  DWARFUnitInterface &operator=(const DWARFUnitInterface &) = delete;
+};
+
+class DWARFUnit : public UserID, public DWARFUnitInterface {
   using die_iterator_range =
       llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
 
@@ -116,12 +143,14 @@ class DWARFUnit : public UserID {
   size_t GetDebugInfoSize() const;
   // Size of the CU data incl. header but without initial length.
   dw_offset_t GetLength() const { return m_header.getLength(); }
-  uint16_t GetVersion() const { return m_header.getVersion(); }
+  uint16_t GetVersion() const override { return m_header.getVersion(); }
   const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
   dw_offset_t GetAbbrevOffset() const;
-  uint8_t GetAddressByteSize() const { return m_header.getAddressByteSize(); }
+  uint8_t GetAddressByteSize() const override {
+    return m_header.getAddressByteSize();
+  }
   dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); }
-  dw_addr_t GetBaseAddress() const { return m_base_addr; }
+  dw_addr_t GetBaseAddress() const override { return m_base_addr; }
   dw_offset_t GetLineTableOffset();
   dw_addr_t GetRangesBase() const { return m_ranges_base; }
   dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
@@ -131,7 +160,7 @@ class DWARFUnit : public UserID {
   void SetStrOffsetsBase(dw_offset_t str_offsets_base);
   virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
 
-  dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const;
+  dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const override;
 
   lldb::ByteOrder GetByteOrder() const;
 
@@ -145,6 +174,9 @@ class DWARFUnit : public UserID {
 
   DWARFDIE GetDIE(dw_offset_t die_offset);
 
+  llvm::Error GetBitSizeAndSign(uint64_t die_offset, uint64_t &bit_size,
+                                bool &sign) override;
+
   /// Returns the AT_Name of the DIE at `die_offset`, if it exists, without
   /// parsing the entire compile unit. An empty is string is returned upon
   /// error or if the attribute is not present.
@@ -152,10 +184,6 @@ class DWARFUnit : public UserID {
 
   DWARFUnit &GetNonSkeletonUnit();
 
-  static uint8_t GetAddressByteSize(const DWARFUnit *cu);
-
-  static uint8_t GetDefaultAddressSize();
-
   lldb_private::CompileUnit *GetLLDBCompUnit() const { return m_lldb_cu; }
 
   void SetLLDBCompUnit(lldb_private::CompileUnit *cu) { m_lldb_cu = cu; }
@@ -174,7 +202,7 @@ class DWARFUnit : public UserID {
 
   bool Supports_unnamed_objc_bitfields();
 
-  SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; }
+  SymbolFileDWARF &GetSymbolFileDWARF() const override { return m_dwarf; }
 
   DWARFProducer GetProducer();
 
@@ -237,7 +265,7 @@ class DWARFUnit : public UserID {
   /// Return the location table for parsing the given location list data. The
   /// format is chosen according to the unit type. Never returns null.
   std::unique_ptr<llvm::DWARFLocationTable>
-  GetLocationTable(const DataExtractor &data) const;
+  GetLocationTable(const DataExtractor &data) const override;
 
   DWARFDataExtractor GetLocationData() const;
 

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something like this makes sense, but if we're doing this, I think we should do it properly and actually remove the DWARFExpression->SymbolFileDWARF dependency. We can't do that if DWARFUnitInterface is defined in the symbol file plugin, nor while it contains methods like GetSymbolFileDWARF(). Moving the interface definition elsewhere is easy. The second part requires some thought. It looks like the main use for that method is to provide vendor extensibility for dwarf parsing, so I think we should expose that as an interface (i.e., have methods like ParseVendorDWARFOpcodeSize and GetVendorDWARFOpcodeSize) instead of the raw DWARF symbol file.

For this reason, I also think the interface shouldn't be called DWARFUnitInterface, but rather something centred on DWARFExpression and the things it needs from its users. For lack of imagination, I'm going to suggest DWARFExpression::Delegate (because we already use that term in some places), but maybe we'll come up with something more specific in the process. (This means it may not make sense to DWARFUnit to inherit from DWARFExpression::Delegate, but that's okay -- we can always use composition instead)

I also want to look at each function in that interface and see if it's really necessary. Two examples:

  • GetLocationTable is only used from ParseDWARFLocationList and that is only used from DWARF plugin code. Instead of adding this to the interface, I think we should move ParseDWARFLocationList into the DWARF plugin. (This can/should be a separate patch)
  • I'm not sure that GetAddressByteSize is necessary since the DataExtractor member (m_data) already has a method with the same name (and it's even used in some places). Before adding that to the interface, I'd like to see if we can make everything use the value in m_data instead.

Moved ParseDWARFLocationList to DWARF plugin.
@slydiman slydiman requested a review from labath March 18, 2025 18:10
@slydiman slydiman changed the title [LLDB][NFC] Added the interface DWARFUnitInterface to break dependencies and reduce lldb-server size [LLDB][NFC] Added the interface DWARFExpression::Delegate to break dependencies and reduce lldb-server size Mar 19, 2025
@slydiman
Copy link
Contributor Author

After this patch and #132274 the size of lldb-server is reduced from 47MB to 8MB.

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually very much like this result. It'd be nice to (try) get rid of the GetAddressByteSize method, as I outlined before, but that's better done separately. Just a couple of small changes/improvements inline.

Comment on lines 46 to 48
virtual llvm::Error GetDIEBitSizeAndSign(uint64_t die_offset,
uint64_t &bit_size,
bool &sign) = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
virtual llvm::Error GetDIEBitSizeAndSign(uint64_t die_offset,
uint64_t &bit_size,
bool &sign) = 0;
virtual llvm::Expected<std::pair<uint64_t, bool>> GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0;

(I'm prioritizing the interface over implementation, so I'm making the method const. You can put the const_cast into the implementation (I think it's only needed for GetDIE. I am also emphasizing the relativeness of the die offset as lldb default is to use absolute section offsets)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (!bit_size)
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
if (!bit_size)
return llvm::createStringError("unsupported type size in DW_OP_convert");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return llvm::createStringError("unsupported type size in DW_OP_convert");
return llvm::createStringError("unsupported type size");

Let's not mention DW_OP_convert here. (same below)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 744 to 746
bool DWARFUnit::ParseDWARFLocationList(
const DataExtractor &data, DWARFExpressionList *location_list) const {
location_list->Clear();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change this to a reference while we're here.

Suggested change
bool DWARFUnit::ParseDWARFLocationList(
const DataExtractor &data, DWARFExpressionList *location_list) const {
location_list->Clear();
bool DWARFUnit::ParseDWARFLocationList(
const DataExtractor &data, DWARFExpressionList &location_list) const {
location_list.Clear();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -38,7 +39,7 @@ enum DWARFProducer {
eProducerOther
};

class DWARFUnit : public UserID {
class DWARFUnit : public UserID, public DWARFExpression::Delegate {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class DWARFUnit : public UserID, public DWARFExpression::Delegate {
class DWARFUnit : public DWARFExpression::Delegate, public UserID {

(because Delegate is a "true" base class (with virtual methods and whatnot) while UserID is a mixin)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -37,7 +36,6 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"

#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does all this mean this header can be removed now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because the code which is required this header has been moved to DWARFUnit.cpp

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove it then? :)

@slydiman slydiman requested a review from labath March 21, 2025 14:28
@@ -37,7 +36,6 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"

#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove it then? :)

…ression.cpp

Moved DW_OP_value_to_name() from DWARFDefines.cpp to DWARFExpression.cpp
@slydiman
Copy link
Contributor Author

@labath
I have removed #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" from DWARFExpression.cpp and moved the helper DW_OP_value_to_name() from DWARFDefines.cpp to DWARFExpression.cpp

@slydiman slydiman merged commit 2edf534 into llvm:main Mar 24, 2025
10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 24, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/14835

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: lang/cpp/stl/TestSTL.py (862 of 2109)
XFAIL: lldb-api :: lang/cpp/thread_local/TestThreadLocal.py (863 of 2109)
XFAIL: lldb-api :: lang/cpp/trivial_abi/TestTrivialABI.py (864 of 2109)
PASS: lldb-api :: lang/cpp/type_lookup/TestCppTypeLookup.py (865 of 2109)
PASS: lldb-api :: lang/cpp/typedef-to-outer-fwd/TestTypedefToOuterFwd.py (866 of 2109)
PASS: lldb-api :: lang/cpp/type_lookup_duplicate/TestCppTypeLookupDuplicate.py (867 of 2109)
PASS: lldb-api :: lang/cpp/typeof/TestTypeOfDeclTypeExpr.py (868 of 2109)
PASS: lldb-api :: lang/cpp/thunk/TestThunk.py (869 of 2109)
PASS: lldb-api :: lang/cpp/typedef/TestCppTypedef.py (870 of 2109)
PASS: lldb-api :: lang/cpp/template/TestTemplateArgs.py (871 of 2109)
FAIL: lldb-api :: lang/cpp/unique-types/TestUniqueTypes.py (872 of 2109)
******************** TEST 'lldb-api :: lang/cpp/unique-types/TestUniqueTypes.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/lang/cpp/unique-types -p TestUniqueTypes.py
--
Exit Code: -11

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 2edf534f5542a02f3ea3c70effb9503c99add809)
  clang revision 2edf534f5542a02f3ea3c70effb9503c99add809
  llvm revision 2edf534f5542a02f3ea3c70effb9503c99add809
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_dsym (TestUniqueTypes.UniqueTypesTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_dwarf (TestUniqueTypes.UniqueTypesTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_dwo (TestUniqueTypes.UniqueTypesTestCase)
----------------------------------------------------------------------
Ran 3 tests in 1.022s

OK (skipped=1)

--

********************
PASS: lldb-api :: lang/cpp/unique-types2/TestUniqueTypes2.py (873 of 2109)
PASS: lldb-api :: lang/cpp/unsigned_types/TestUnsignedTypes.py (874 of 2109)
PASS: lldb-api :: lang/cpp/unique-types3/TestUniqueTypes3.py (875 of 2109)
PASS: lldb-api :: lang/cpp/unicode-literals/TestUnicodeLiterals.py (876 of 2109)
PASS: lldb-api :: lang/cpp/union-static-data-members/TestCppUnionStaticMembers.py (877 of 2109)
PASS: lldb-api :: lang/cpp/unique-types4/TestUniqueTypes4.py (878 of 2109)
PASS: lldb-api :: lang/cpp/virtual-overload/TestVirtualOverload.py (879 of 2109)
UNSUPPORTED: lldb-api :: lang/objc/bitfield_ivars/TestBitfieldIvars.py (880 of 2109)
UNSUPPORTED: lldb-api :: lang/objc/blocks/TestObjCIvarsInBlocks.py (881 of 2109)
UNSUPPORTED: lldb-api :: lang/objc/charstar_dyntype/TestCharStarDynType.py (882 of 2109)

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Mar 25, 2025
…tion

In rdar://147772462 a merge conflict occured due to this upstream
commit:

```
commit 2edf534
Author: Dmitry Vasilyev <[email protected]>
Date:   Mon Mar 24 18:40:49 2025 +0400

    [LLDB][NFC] Added the interface DWARFExpression::Delegate to break dependencies and reduce lldb-server size (llvm#131645)
```

I resolved the conflict but it failed to build. This patch unbreaks the
build but only when `LLDB_ENABLE_SWIFT` is OFF. This will hopefully be
enough to unblock the automergers. The build will almost certainly be
broken when `LLDB_ENABLE_SWIFT` is ON but I don't understand the code
well enough to fix it correctly so the LLDB folks will need to properly
resolve this in a follow up patch.

rdar://147795421
@felipepiovezan
Copy link
Contributor

Should this also change the interface of DWAFExpressionList?

  DWARFExpressionList(lldb::ModuleSP module_sp,
                      const plugin::dwarf::DWARFUnit *dwarf_cu,
                      lldb::addr_t func_file_addr)
      : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu),
        m_func_file_addr(func_file_addr) {}

  DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr,
                      const plugin::dwarf::DWARFUnit *dwarf_cu)
      : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu) {
    AddExpression(0, LLDB_INVALID_ADDRESS, expr);
  }

@felipepiovezan
Copy link
Contributor

This type of patch also slightly worries me in that it could make it harder to unify the LLDB dwarf data structures with the LLVM ones

@slydiman
Copy link
Contributor Author

Should this also change the interface of DWAFExpressionList?

Yes, I will prepare the patch. Thanks

slydiman added a commit to slydiman/llvm-project that referenced this pull request Mar 26, 2025
@labath
Copy link
Collaborator

labath commented Mar 26, 2025

This type of patch also slightly worries me in that it could make it harder to unify the LLDB dwarf data structures with the LLVM ones

That is something I considered, but I think this might actually help with that. At this point the LLDB and llvm dwarf classes are so different, that the only way I see to unify them is to do it piecemeal, and this kind of decoupling helps with that. So, if you wanted to replace LLDB DWARFUnit with llvm's, you could do that without touching DWARFExpression. It's true lldb's DWARFUnit now inherits from some DWARFExpression thingy, but that's easy to replace with composition. I alluded to that in the earlier comments, but in the end I didn't insist on it. Maybe I should have. If you think it's better to do that now, I'd be certainly fine with that.

This doesn't help with replacing LLDB's DWARFExpression with the llvm version, but I don't think it makes it worse either. I see a couple of possible ways forwards there:

  • introduce a similar abstraction to llvm DWARFExpression. I think that would make sense since dwarf expressions are used in contexts (eh_frame) where there is no DWARFUnit to speak of.
  • replace (non-unwinding) uses of DWARF Expression with a higher level abstraction. It's use in Function and Variable classes is breaking abstractions, and the PDB plugin has to jump through hoops to create DWARF expressions for these objects. That would leave DWARFExpression only used for unwinding in the core code, where it would be easier to replace this with llvm::DWARFExpression (and at that point, it may not matter that it depends on llvm::DWARFUnit, since this class -- unlike the lldb counterpart -- does not depend on the whole world)

slydiman added a commit that referenced this pull request Mar 26, 2025
@slydiman slydiman deleted the lldb-server-reduce-size branch April 18, 2025 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants