Skip to content

[LLDB] Respect the DW_AT_alignment attribute. #73307

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 3 commits into from
Nov 28, 2023
Merged

Conversation

hokein
Copy link
Collaborator

@hokein hokein commented Nov 24, 2023

Part of fixes for #72913.

clang emits DW_AT_alignment attribute, however LLDB didn't respect it, resulting in incorrect RecordDecls built by lldb.

This only fixes non-inheritance cases. The inheritance case will be handled in a follow-up patch.

Part of fixes for llvm#72913.

clang emits the DW_AT_alignment attribute, however LLDB didn't respect it,
resulting an incorrect the RecordDecl built by lldb.

This only fixes non-inheritance cases. The inheritance case
will be handled in a follow-up patch.
@hokein hokein requested a review from Michael137 November 24, 2023 09:53
@hokein hokein requested a review from JDevlieghere as a code owner November 24, 2023 09:53
@llvmbot llvmbot added the lldb label Nov 24, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 24, 2023

@llvm/pr-subscribers-lldb

Author: Haojian Wu (hokein)

Changes

Part of fixes for #72913.

clang emits DW_AT_alignment attribute, however LLDB didn't respect it, resulting in incorrect RecordDecls built by lldb.

This only fixes non-inheritance cases. The inheritance case will be handled in a follow-up patch.


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

4 Files Affected:

  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+10-2)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h (+1)
  • (modified) lldb/test/API/lang/cpp/alignas_base_class/TestAlignAsBaseClass.py (+4)
  • (modified) lldb/test/API/lang/cpp/alignas_base_class/main.cpp (+2)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index abe3c673e2cce69..a55ca0bf0f0fc1a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -355,6 +355,10 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
       byte_size = form_value.Unsigned();
       break;
 
+    case DW_AT_alignment:
+      alignment = form_value.Unsigned();
+      break;
+
     case DW_AT_byte_stride:
       byte_stride = form_value.Unsigned();
       break;
@@ -1926,12 +1930,13 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
       // TypeSystemClang is always in C++ mode, but some compilers such as
       // GCC and Clang give empty structs a size of 0 in C mode (in contrast to
       // the size of 1 for empty structs that would be computed in C++ mode).
-      if (attrs.byte_size) {
+      if (attrs.byte_size || attrs.alignment) {
         clang::RecordDecl *record_decl =
             TypeSystemClang::GetAsRecordDecl(clang_type);
         if (record_decl) {
           ClangASTImporter::LayoutInfo layout;
-          layout.bit_size = *attrs.byte_size * 8;
+          layout.bit_size = attrs.byte_size.value_or(0) * 8;
+          layout.alignment = attrs.alignment.value_or(0) * 8;
           GetClangASTImporter().SetRecordLayout(record_decl, layout);
         }
       }
@@ -2270,6 +2275,9 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
     if (layout_info.bit_size == 0)
       layout_info.bit_size =
           die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+    if (layout_info.alignment == 0)
+      layout_info.alignment =
+          die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8;
 
     clang::CXXRecordDecl *record_decl =
         m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 0247783217008e8..81b705a036189eb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -456,6 +456,7 @@ struct ParsedDWARFTypeAttributes {
   lldb_private::plugin::dwarf::DWARFFormValue type;
   lldb::LanguageType class_language = lldb::eLanguageTypeUnknown;
   std::optional<uint64_t> byte_size;
+  std::optional<uint64_t> alignment;
   size_t calling_convention = llvm::dwarf::DW_CC_normal;
   uint32_t bit_stride = 0;
   uint32_t byte_stride = 0;
diff --git a/lldb/test/API/lang/cpp/alignas_base_class/TestAlignAsBaseClass.py b/lldb/test/API/lang/cpp/alignas_base_class/TestAlignAsBaseClass.py
index c7a88987733e176..7d97b0c42b7e166 100644
--- a/lldb/test/API/lang/cpp/alignas_base_class/TestAlignAsBaseClass.py
+++ b/lldb/test/API/lang/cpp/alignas_base_class/TestAlignAsBaseClass.py
@@ -12,3 +12,7 @@ def test(self):
 
         # The offset of f2 should be 8 because of `alignas(8)`.
         self.expect_expr("(intptr_t)&d3g.f2 - (intptr_t)&d3g", result_value="8")
+
+        # Verify specified class alignments.
+        self.expect_expr("alignof(B2)", result_value="8")
+        self.expect_expr("alignof(EmptyClassAlign8)", result_value="8")
diff --git a/lldb/test/API/lang/cpp/alignas_base_class/main.cpp b/lldb/test/API/lang/cpp/alignas_base_class/main.cpp
index 8dfced6c784e102..cf727e808017bcc 100644
--- a/lldb/test/API/lang/cpp/alignas_base_class/main.cpp
+++ b/lldb/test/API/lang/cpp/alignas_base_class/main.cpp
@@ -10,4 +10,6 @@ struct D : B1, B2 {};
 
 D d3g;
 
+struct alignas(8) EmptyClassAlign8 {} t;
+
 int main() {}

Copy link

github-actions bot commented Nov 24, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

clang::RecordDecl *record_decl =
TypeSystemClang::GetAsRecordDecl(clang_type);
if (record_decl) {
ClangASTImporter::LayoutInfo layout;
layout.bit_size = *attrs.byte_size * 8;
layout.bit_size = attrs.byte_size.value_or(0) * 8;
layout.alignment = attrs.alignment.value_or(0) * 8;
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this extra accounting for alignment here? This block used to be solely for cases where empty structs had special byte-size requirements. Is it because in your tests alignof(EmptyStruct) wouldn't trigger CompleteRecordType?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is it because in your tests alignof(EmptyStruct) wouldn't trigger CompleteRecordType?

Yes, exactly, this is the major reason. The codepath in CompleteRecordType has a conditional statement if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() || !layout_info.vbase_offsets.empty()) where an empty structure will never hit.

We could tweak the if condition there, but I'm less certain about it, my reading of code is that the location here seem to be responsible for empty structures (happy to change if this is not reasonable).

Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks fine to me. If we have a byte size computed by clang, it was always using it and it helped with C structs being computed in a C++ type system when the size was zero or 1. Now we will also respect the alignment. Also the ClangASTImporter::LayoutInfo::bit_size is initialized to zero in the header file, so even though we will make it into this case now if we have only alignment,it shouldn't change anything AFAIK.

Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

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

LGTM

clang::RecordDecl *record_decl =
TypeSystemClang::GetAsRecordDecl(clang_type);
if (record_decl) {
ClangASTImporter::LayoutInfo layout;
layout.bit_size = *attrs.byte_size * 8;
layout.bit_size = attrs.byte_size.value_or(0) * 8;
layout.alignment = attrs.alignment.value_or(0) * 8;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks fine to me. If we have a byte size computed by clang, it was always using it and it helped with C structs being computed in a C++ type system when the size was zero or 1. Now we will also respect the alignment. Also the ClangASTImporter::LayoutInfo::bit_size is initialized to zero in the header file, so even though we will make it into this case now if we have only alignment,it shouldn't change anything AFAIK.

Copy link
Collaborator Author

@hokein hokein left a comment

Choose a reason for hiding this comment

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

Thanks for the review.

@hokein
Copy link
Collaborator Author

hokein commented Nov 28, 2023

@Michael137, I'm merging this patch now. I'm happy to address any post comments.

@hokein hokein merged commit 439b16e into llvm:main Nov 28, 2023
@hokein hokein deleted the class-alignas branch November 28, 2023 11:28
@Michael137
Copy link
Member

LGTM, I don't expect this to change with any of the other outstanding bugs, so seems fine to merge now

augusto2112 pushed a commit to augusto2112/llvm-project that referenced this pull request Jun 28, 2024
Part of fixes for llvm#72913.

clang emits `DW_AT_alignment` attribute, however LLDB didn't respect it,
resulting in incorrect RecordDecls built by lldb.

This only fixes non-inheritance cases. The inheritance case will be
handled in a follow-up patch.

(cherry picked from commit 439b16e)
augusto2112 pushed a commit to augusto2112/llvm-project that referenced this pull request Sep 11, 2024
Part of fixes for llvm#72913.

clang emits `DW_AT_alignment` attribute, however LLDB didn't respect it,
resulting in incorrect RecordDecls built by lldb.

This only fixes non-inheritance cases. The inheritance case will be
handled in a follow-up patch.

(cherry picked from commit 439b16e)
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.

4 participants