[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