[Lldb-commits] [lldb] r167424 - in /lldb/trunk/source: Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Symbol/ClangASTContext.cpp

Greg Clayton gclayton at apple.com
Mon Nov 5 16:20:41 PST 2012


Author: gclayton
Date: Mon Nov  5 18:20:41 2012
New Revision: 167424

URL: http://llvm.org/viewvc/llvm-project?rev=167424&view=rev
Log:
<rdar://problem/12582031> 

Unnamed bitfields cause struct layout problems

Synthesize unnamed bitfields when required. Most compilers don't mention unnamed bitfields in the DWARF, so we need to create them to keep clang happy with the types we create from the DWARF. We currently can't do this for ObjC since the DW_AT_bit_offset value for any direct ivars of ObjC classes as the values for these attributes are bogus. A bug has been filed on Clang to fix this, and another bug has been filed on LLDB to make sure we fix the DWARF parser once the clang fix is in by looking the the DW_AT_producer in the compile unit attributes and finding the compiler version and only enabling it for newer versions of clang.


Modified:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=167424&r1=167423&r2=167424&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Mon Nov  5 18:20:41 2012
@@ -1556,6 +1556,7 @@
     std::vector<clang::CXXBaseSpecifier *>& base_classes,
     std::vector<int>& member_accessibilities,
     DWARFDIECollection& member_function_dies,
+    BitfieldMap &bitfield_map,
     DelayedPropertyList& delayed_properties,
     AccessType& default_accessibility,
     bool &is_a_class,
@@ -1759,7 +1760,84 @@
                                     accessibility = default_accessibility;
                                 member_accessibilities.push_back(accessibility);
 
-                                field_decl = GetClangASTContext().AddFieldToRecordType (class_clang_type, 
+                                // Code to detect unnamed bitifields
+                                if (bit_size > 0 && member_byte_offset != UINT32_MAX)
+                                {
+                                    // Objective C has invalid DW_AT_bit_offset values so we can't use them to detect
+                                    // unnamed bitfields. Once clang is fixed we will enable unnamed bitfields
+                                    // in ObjC classes (<rdar://problem/12636970>)
+                                    
+                                    if (!(class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus))
+                                    {
+                                        // We have a bitfield, we need to watch out for
+                                        // unnamed bitfields that we need to insert if
+                                        // there is a gap in the bytes as many compilers
+                                        // doesn't emit DWARF DW_TAG_member tags for
+                                        // unnammed bitfields.
+                                        BitfieldMap::iterator bit_pos = bitfield_map.find(member_byte_offset);
+                                        uint32_t unnamed_bit_size = 0;
+                                        uint32_t unnamed_bit_offset = 0;
+                                        if (bit_pos == bitfield_map.end())
+                                        {
+                                            // First bitfield in an integral type.
+                                            
+                                            // We might need to insert a leading unnamed bitfield
+                                            if (bit_offset < byte_size * 8)
+                                            {
+                                                unnamed_bit_size = byte_size * 8 - (bit_size + bit_offset);
+                                                unnamed_bit_offset = byte_size * 8 - unnamed_bit_size;
+                                            }
+                                            
+                                            // Now put the current bitfield info into the map
+                                            bitfield_map[member_byte_offset].bit_size = bit_size;
+                                            bitfield_map[member_byte_offset].bit_offset = bit_offset;
+                                        }
+                                        else
+                                        {
+                                            // Subsequent bitfield in an integral type.
+
+                                            // We have a bitfield that isn't the first for this
+                                            // integral type, check to make sure there aren't any
+                                            // gaps.
+                                            assert (bit_pos->second.bit_size > 0);
+                                            if (bit_offset < bit_pos->second.bit_offset)
+                                            {
+                                                unnamed_bit_size = bit_pos->second.bit_offset - (bit_size + bit_offset);
+                                                unnamed_bit_offset = bit_pos->second.bit_offset - unnamed_bit_size;
+                                            }
+
+                                            // Now put the current bitfield info into the map
+                                            bit_pos->second.bit_size = bit_size;
+                                            bit_pos->second.bit_offset = bit_offset;
+                                        }
+                                        
+                                        if (unnamed_bit_size > 0)
+                                        {
+                                            //printf ("0x%8.8x: Unnamed bitfield added bit_size = 0x%x, bit_offset = 0x%x\n", die->GetOffset(), unnamed_bit_size, unnamed_bit_offset);
+                                            clang::FieldDecl *unnamed_bitfield_decl = GetClangASTContext().AddFieldToRecordType (class_clang_type,
+                                                                                                                                 NULL,
+                                                                                                                                 member_type->GetClangLayoutType(),
+                                                                                                                                 accessibility,
+                                                                                                                                 unnamed_bit_size);
+                                            uint64_t total_bit_offset = 0;
+                                            
+                                            total_bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+                                            
+                                            if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
+                                            {
+                                                total_bit_offset += byte_size * 8;
+                                                total_bit_offset -= (unnamed_bit_offset + unnamed_bit_size);
+                                            }
+                                            else
+                                            {
+                                                total_bit_offset += unnamed_bit_size;
+                                            }
+                                            
+                                            layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, total_bit_offset));
+                                        }
+                                    }
+                                }
+                                field_decl = GetClangASTContext().AddFieldToRecordType (class_clang_type,
                                                                                         name, 
                                                                                         member_type->GetClangLayoutType(), 
                                                                                         accessibility, 
@@ -1798,13 +1876,11 @@
                                 // AT_bit_size indicates the size of the field in bits.
                                 /////////////////////////////////////////////////////////////
                                                         
-                                ByteOrder object_endian = GetObjectFile()->GetModule()->GetArchitecture().GetDefaultEndian();
-
                                 uint64_t total_bit_offset = 0;
                                 
                                 total_bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
                                 
-                                if (object_endian == eByteOrderLittle)
+                                if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
                                 {  
                                     total_bit_offset += byte_size * 8;
                                     total_bit_offset -= (bit_offset + bit_size);
@@ -2167,8 +2243,8 @@
                     DWARFDIECollection member_function_dies;
                                         
                     DelayedPropertyList delayed_properties;
-                    
-                    ParseChildMembers (sc, 
+                    BitfieldMap bitfield_map;
+                    ParseChildMembers (sc,
                                        dwarf_cu,
                                        die, 
                                        clang_type,
@@ -2176,6 +2252,7 @@
                                        base_classes, 
                                        member_accessibilities,
                                        member_function_dies,
+                                       bitfield_map,
                                        delayed_properties,
                                        default_accessibility, 
                                        is_a_class,

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=167424&r1=167423&r2=167424&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Mon Nov  5 18:20:41 2012
@@ -59,6 +59,14 @@
 class DWARFFormValue;
 class SymbolFileDWARFDebugMap;
 
+struct BitfieldInfo
+{
+    uint32_t bit_size;
+    uint32_t bit_offset;
+};
+
+typedef std::map<int64_t, BitfieldInfo> BitfieldMap;
+
 class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
 {
 public:
@@ -345,6 +353,7 @@
                                 std::vector<clang::CXXBaseSpecifier *>& base_classes,
                                 std::vector<int>& member_accessibilities,
                                 DWARFDIECollection& member_function_dies,
+                                BitfieldMap &bitfield_map,
                                 DelayedPropertyList& delayed_properties,
                                 lldb::AccessType &default_accessibility,
                                 bool &is_a_class,

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=167424&r1=167423&r2=167424&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Mon Nov  5 18:20:41 2012
@@ -2366,7 +2366,7 @@
                                               class_interface_decl,
                                               SourceLocation(),
                                               SourceLocation(),
-                                              &identifier_table->get(name), // Identifier
+                                              name ? &identifier_table->get(name) : NULL, // Identifier
                                               QualType::getFromOpaquePtr(ivar_opaque_type), // Field type
                                               NULL, // TypeSourceInfo *
                                               ConvertAccessTypeToObjCIvarAccessControl (access),





More information about the lldb-commits mailing list