Skip to content

Commit

Permalink
<rdar://problem/12582031>
Browse files Browse the repository at this point in the history
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.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@167424 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Greg Clayton committed Nov 6, 2012
1 parent 2c5ccde commit f270fa9
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 7 deletions.
89 changes: 83 additions & 6 deletions source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,7 @@ SymbolFileDWARF::ParseChildMembers
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,
Expand Down Expand Up @@ -1759,7 +1760,84 @@ SymbolFileDWARF::ParseChildMembers
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,
Expand Down Expand Up @@ -1798,13 +1876,11 @@ SymbolFileDWARF::ParseChildMembers
// 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);
Expand Down Expand Up @@ -2167,15 +2243,16 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_type
DWARFDIECollection member_function_dies;

DelayedPropertyList delayed_properties;

ParseChildMembers (sc,
BitfieldMap bitfield_map;
ParseChildMembers (sc,
dwarf_cu,
die,
clang_type,
class_language,
base_classes,
member_accessibilities,
member_function_dies,
bitfield_map,
delayed_properties,
default_accessibility,
is_a_class,
Expand Down
9 changes: 9 additions & 0 deletions source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ class DWARFDIECollection;
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:
Expand Down Expand Up @@ -345,6 +353,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::Us
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,
Expand Down
2 changes: 1 addition & 1 deletion source/Symbol/ClangASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2366,7 +2366,7 @@ ClangASTContext::AddObjCClassIVar
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),
Expand Down

0 comments on commit f270fa9

Please sign in to comment.