[llvm] [llvm-debuginfo-analyzer] Add support for DWARF `DW_AT_byte_size` (PR #139110)

Javier Lopez-Gomez via llvm-commits llvm-commits at lists.llvm.org
Mon May 12 05:33:34 PDT 2025


https://github.com/jalopezg-git updated https://github.com/llvm/llvm-project/pull/139110

>From 1dd824cebf7e15719fbecdf2bab28ea68b87e97c Mon Sep 17 00:00:00 2001
From: Javier Lopez-Gomez <javier.lopez.gomez at proton.me>
Date: Fri, 25 Apr 2025 16:27:25 +0200
Subject: [PATCH] [llvm-debuginfo-analyzer] Add support for DWARF
 `DW_AT_byte_size`

---
 .../DebugInfo/LogicalView/Core/LVElement.h    |  7 ++++
 .../llvm/DebugInfo/LogicalView/Core/LVScope.h |  6 +++
 .../llvm/DebugInfo/LogicalView/Core/LVType.h  |  7 ++++
 .../DebugInfo/LogicalView/Core/LVScope.cpp    |  6 ++-
 .../lib/DebugInfo/LogicalView/Core/LVType.cpp |  5 ++-
 .../LogicalView/Readers/LVCodeViewVisitor.cpp |  3 ++
 .../LogicalView/Readers/LVDWARFReader.cpp     |  3 ++
 .../COFF/06-coff-full-logical-view.test       |  6 +--
 .../DWARF/06-dwarf-full-logical-view.test     |  6 +--
 .../LogicalView/CodeViewReaderTest.cpp        | 41 +++++++++++++++++++
 .../DebugInfo/LogicalView/DWARFReaderTest.cpp |  6 +++
 11 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
index 17fa04040ad77..b2ef6579caf41 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
@@ -64,6 +64,10 @@ using LVElementKindSet = std::set<LVElementKind>;
 using LVElementDispatch = std::map<LVElementKind, LVElementGetFunction>;
 using LVElementRequest = std::vector<LVElementGetFunction>;
 
+// Assume 8-bit bytes; this is consistent, e.g. with
+// lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp.
+constexpr unsigned int DWARF_CHAR_BIT = 8u;
+
 class LVElement : public LVObject {
   enum class Property {
     IsLine,   // A logical line.
@@ -239,6 +243,9 @@ class LVElement : public LVObject {
   virtual bool isBase() const { return false; }
   virtual bool isTemplateParam() const { return false; }
 
+  uint32_t getStorageSizeInBytes() const {
+    return (getBitSize() + (DWARF_CHAR_BIT - 1)) / DWARF_CHAR_BIT;
+  }
   virtual uint32_t getBitSize() const { return 0; }
   virtual void setBitSize(uint32_t Size) {}
 
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
index 1b3c377cd7dbb..1cf61d085d84f 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
@@ -93,6 +93,9 @@ class LVScope : public LVElement {
   LVProperties<Property> Properties;
   static LVScopeDispatch Dispatch;
 
+  // Size in bits if this scope represents also a compound type.
+  uint32_t BitSize = 0;
+
   // Coverage factor in units (bytes).
   unsigned CoverageFactor = 0;
 
@@ -269,6 +272,9 @@ class LVScope : public LVElement {
   bool removeElement(LVElement *Element) override;
   void updateLevel(LVScope *Parent, bool Moved) override;
 
+  uint32_t getBitSize() const override { return BitSize; }
+  void setBitSize(uint32_t Size) override { BitSize = Size; }
+
   void resolve() override;
   void resolveName() override;
   void resolveReferences() override;
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
index 28881b3c95b17..58d5bc48c3a72 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h
@@ -56,6 +56,9 @@ class LVType : public LVElement {
   LVProperties<Property> Properties;
   static LVTypeDispatch Dispatch;
 
+  // Size in bits of a symbol of this type.
+  uint32_t BitSize = 0;
+
   // Find the current type in the given 'Targets'.
   LVType *findIn(const LVTypes *Targets) const;
 
@@ -109,6 +112,10 @@ class LVType : public LVElement {
   virtual LVElement *getUnderlyingType() { return nullptr; }
   virtual void setUnderlyingType(LVElement *Element) {}
 
+  // Return the size in bits of an entity of this type.
+  uint32_t getBitSize() const override { return BitSize; }
+  void setBitSize(uint32_t Size) override { BitSize = Size; }
+
   void resolveName() override;
   void resolveReferences() override;
 
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
index 8bbaf93db0caa..e4bdf81446c83 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
@@ -1011,9 +1011,13 @@ void LVScope::printExtra(raw_ostream &OS, bool Full) const {
   // Do not print any type or name for a lexical block.
   if (!getIsBlock()) {
     OS << " " << formattedName(getName());
-    if (!getIsAggregate())
+    if (getIsAggregate()) {
+      if (uint32_t Size = getStorageSizeInBytes())
+        OS << " [Size = " << Size << "]";
+    } else {
       OS << " -> " << typeOffsetAsString()
          << formattedNames(getTypeQualifiedName(), typeAsString());
+    }
   }
   OS << "\n";
 
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp
index 28bccadce598c..e5c9936c008e2 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp
@@ -292,7 +292,10 @@ void LVType::print(raw_ostream &OS, bool Full) const {
 }
 
 void LVType::printExtra(raw_ostream &OS, bool Full) const {
-  OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
+  OS << formattedKind(kind()) << " " << formattedName(getName());
+  if (uint32_t Size = getStorageSizeInBytes())
+    OS << " [Size = " << Size << "]";
+  OS << "\n";
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
index 97214948d014a..4a1eb888095e2 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
@@ -1987,6 +1987,7 @@ Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class,
   Scope->setName(Class.getName());
   if (Class.hasUniqueName())
     Scope->setLinkageName(Class.getUniqueName());
+  Scope->setBitSize(Class.getSize() * DWARF_CHAR_BIT);
 
   if (Class.isNested()) {
     Scope->setIsNested();
@@ -2455,6 +2456,7 @@ Error LVLogicalVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union,
   Scope->setName(Union.getName());
   if (Union.hasUniqueName())
     Scope->setLinkageName(Union.getUniqueName());
+  Scope->setBitSize(Union.getSize() * DWARF_CHAR_BIT);
 
   if (Union.isNested()) {
     Scope->setIsNested();
@@ -3208,6 +3210,7 @@ LVType *LVLogicalVisitor::createBaseType(TypeIndex TI, StringRef TypeName) {
 
   if (createElement(TIR, SimpleKind)) {
     CurrentType->setName(TypeName);
+    CurrentType->setBitSize(getSizeInBytesForTypeIndex(TIR) * DWARF_CHAR_BIT);
     Reader->getCompileUnit()->addElement(CurrentType);
   }
   return CurrentType;
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
index 42da957233667..269630896e077 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
@@ -307,6 +307,9 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
   case dwarf::DW_AT_bit_size:
     CurrentElement->setBitSize(GetAsUnsignedConstant());
     break;
+  case dwarf::DW_AT_byte_size:
+    CurrentElement->setBitSize(GetAsUnsignedConstant() * DWARF_CHAR_BIT);
+    break;
   case dwarf::DW_AT_call_file:
     CurrentElement->setCallFilenameIndex(IncrementFileIndex
                                              ? GetAsUnsignedConstant() + 1
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/COFF/06-coff-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/COFF/06-coff-full-logical-view.test
index 4e6083be343a0..42c6f124ce70a 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/COFF/06-coff-full-logical-view.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/COFF/06-coff-full-logical-view.test
@@ -34,7 +34,7 @@
 ; ONE-NEXT:                                    {File} 'test.cpp'
 ; ONE-NEXT:                                    {Public} 'foo' [0x0000000000:0x0000000046]
 ; ONE-NEXT: [0x0000000000][002]                {TypeAlias} 'INTPTR' -> [0x0000001001]'* const int'
-; ONE-NEXT: [0x0000000030][002]                {BaseType} 'bool'
+; ONE-NEXT: [0x0000000030][002]                {BaseType} 'bool' [Size = 1]
 ; ONE-NEXT: [0x0000000000][002]                {Function} extern not_inlined 'foo' -> [0x0000000074]'int'
 ; ONE-NEXT: [0x0000000000][003]                  {Range} Lines 2:9 [0x0000000000:0x0000000046]
 ; ONE-NEXT: [0x0000000000][003]                  {Linkage}  0x1 '?foo@@YAHPEBHI_N at Z'
@@ -80,8 +80,8 @@
 ; ONE-NEXT: [0x000000003e][003]                  {Code} 'movl	0x1c(%rsp), %eax'
 ; ONE-NEXT: [0x0000000042][003]                  {Code} 'addq	$0x20, %rsp'
 ; ONE-NEXT: [0x0000000046][003]                  {Code} 'retq'
-; ONE-NEXT: [0x0000000074][002]                {BaseType} 'int'
-; ONE-NEXT: [0x0000000075][002]                {BaseType} 'unsigned'
+; ONE-NEXT: [0x0000000074][002]                {BaseType} 'int' [Size = 4]
+; ONE-NEXT: [0x0000000075][002]                {BaseType} 'unsigned' [Size = 4]
 ; ONE-EMPTY:
 ; ONE-NEXT: -----------------------------
 ; ONE-NEXT: Element      Total    Printed
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test
index e83592afd2ffa..1d0843df52504 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test
@@ -32,9 +32,9 @@
 ; ONE-NEXT:                                    {File} 'test.cpp'
 ; ONE-NEXT:                                    {Public} 'foo' [0x0000000000:0x000000003a]
 ; ONE-NEXT: [0x000000000b][002]                {Range} Lines 2:9 [0x0000000000:0x000000003a]
-; ONE-NEXT: [0x00000000bc][002]                {BaseType} 'bool'
-; ONE-NEXT: [0x0000000099][002]                {BaseType} 'int'
-; ONE-NEXT: [0x00000000b5][002]                {BaseType} 'unsigned int'
+; ONE-NEXT: [0x00000000bc][002]                {BaseType} 'bool' [Size = 1]
+; ONE-NEXT: [0x0000000099][002]                {BaseType} 'int' [Size = 4]
+; ONE-NEXT: [0x00000000b5][002]                {BaseType} 'unsigned int' [Size = 4]
 ; ONE-EMPTY:
 ; ONE-NEXT: [0x00000000a0][002]   {Source} '/data/projects/tests/input/general/test.cpp'
 ; ONE-NEXT: [0x00000000a0][002]      1         {TypeAlias} 'INTPTR' -> [0x00000000ab]'* const int'
diff --git a/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp
index c93a79094dce9..0549aa2976b46 100644
--- a/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp
+++ b/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp
@@ -21,6 +21,7 @@
 #include "llvm/Testing/Support/Error.h"
 
 #include "gtest/gtest.h"
+#include <algorithm>
 
 using namespace llvm;
 using namespace llvm::logicalview;
@@ -128,6 +129,26 @@ void checkElementPropertiesClangCodeview(LVReader *Reader) {
   const LVLines *Lines = Foo->getLines();
   ASSERT_NE(Lines, nullptr);
   EXPECT_EQ(Lines->size(), 0x10u);
+
+  // Check size of types in CompileUnit.
+  const LVTypes *Types = CompileUnit->getTypes();
+  ASSERT_NE(Types, nullptr);
+  EXPECT_EQ(Types->size(), 6u);
+
+  const auto BoolType =
+      std::find_if(Types->begin(), Types->end(), [](const LVElement *elt) {
+        return elt->getName() == "bool";
+      });
+  ASSERT_NE(BoolType, Types->end());
+  const auto IntType =
+      std::find_if(Types->begin(), Types->end(), [](const LVElement *elt) {
+        return elt->getName() == "int";
+      });
+  ASSERT_NE(IntType, Types->end());
+  EXPECT_EQ(static_cast<LVType *>(*BoolType)->getBitSize(), 8u);
+  EXPECT_EQ(static_cast<LVType *>(*BoolType)->getStorageSizeInBytes(), 1u);
+  EXPECT_EQ(static_cast<LVType *>(*IntType)->getBitSize(), 32u);
+  EXPECT_EQ(static_cast<LVType *>(*IntType)->getStorageSizeInBytes(), 4u);
 }
 
 // Check the logical elements basic properties (MSVC - Codeview).
@@ -194,6 +215,26 @@ void checkElementPropertiesMsvcCodeview(LVReader *Reader) {
   const LVLines *Lines = Foo->getLines();
   ASSERT_NE(Lines, nullptr);
   EXPECT_EQ(Lines->size(), 0x0eu);
+
+  // Check size of types in CompileUnit.
+  const LVTypes *Types = CompileUnit->getTypes();
+  ASSERT_NE(Types, nullptr);
+  EXPECT_EQ(Types->size(), 8u);
+
+  const auto BoolType =
+      std::find_if(Types->begin(), Types->end(), [](const LVElement *elt) {
+        return elt->getName() == "bool";
+      });
+  ASSERT_NE(BoolType, Types->end());
+  const auto IntType =
+      std::find_if(Types->begin(), Types->end(), [](const LVElement *elt) {
+        return elt->getName() == "int";
+      });
+  ASSERT_NE(IntType, Types->end());
+  EXPECT_EQ(static_cast<LVType *>(*BoolType)->getBitSize(), 8u);
+  EXPECT_EQ(static_cast<LVType *>(*BoolType)->getStorageSizeInBytes(), 1u);
+  EXPECT_EQ(static_cast<LVType *>(*IntType)->getBitSize(), 32u);
+  EXPECT_EQ(static_cast<LVType *>(*IntType)->getStorageSizeInBytes(), 4u);
 }
 
 // Check the logical elements basic properties (MSVC library - Codeview).
diff --git a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
index c062c15481da9..6c53be959d951 100644
--- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
+++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
@@ -155,6 +155,12 @@ void checkElementSelection(LVReader *Reader) {
   ASSERT_NE(Element, nullptr);
   EXPECT_NE(Element->getName().find("INTEGER"), StringRef::npos);
   EXPECT_EQ(Element->getIsType(), 1);
+  // Underlying type is `int`
+  const LVElement *UnderlyingType =
+      static_cast<LVType *>(Element)->getUnderlyingType();
+  EXPECT_EQ(UnderlyingType->getIsType(), 1);
+  EXPECT_EQ(UnderlyingType->getBitSize(), 32u);
+  EXPECT_EQ(UnderlyingType->getStorageSizeInBytes(), 4u);
 
   Element = MapElements[0x000000000f]; // 'movl	%edx, %eax'
   ASSERT_NE(Element, nullptr);



More information about the llvm-commits mailing list