diff --git a/Source/PDBHeaderReconstructor.cpp b/Source/PDBHeaderReconstructor.cpp index 5d10fe4..0c7d6a0 100644 --- a/Source/PDBHeaderReconstructor.cpp +++ b/Source/PDBHeaderReconstructor.cpp @@ -431,6 +431,62 @@ PDBHeaderReconstructor::OnPaddingMember( } } +void +PDBHeaderReconstructor::OnPaddingBitFieldField( + const SYMBOL_UDT_FIELD* UdtField, + const SYMBOL_UDT_FIELD* PreviousUdtField + ) +{ + WriteIndent(); + + WriteOffset(UdtField, GetParentOffset()); + + // + // Bitfield fields can be unnamed. + // Check if prefix is specified and if not, + // simply do not print anything. + // + + if (m_Settings->BitFieldPaddingMemberPrefix.empty()) + { + Write( + "%s", + PDB::GetBasicTypeString(UdtField->Type) // TODO: UseStdInt + ); + } + else + { + Write( + "%s %s%u", + PDB::GetBasicTypeString(UdtField->Type), // TODO: UseStdInt + m_Settings->PaddingMemberPrefix.c_str(), + m_PaddingMemberCounter++ + ); + } + + // + // BitField handling. + // + + DWORD Bits = PreviousUdtField + ? UdtField->BitPosition - (PreviousUdtField->BitPosition + PreviousUdtField->Bits) + : UdtField->BitPosition; + + DWORD BitPosition = PreviousUdtField + ? PreviousUdtField->BitPosition + PreviousUdtField->Bits + : 0; + + assert(Bits != 0); + + Write(" : %i", Bits); + + Write(";"); + + Write(" /* bit position: %i */", BitPosition); + + Write("\n"); +} + void PDBHeaderReconstructor::Write( const char* Format, diff --git a/Source/PDBHeaderReconstructor.h b/Source/PDBHeaderReconstructor.h index da71c1b..94a8ea7 100644 --- a/Source/PDBHeaderReconstructor.h +++ b/Source/PDBHeaderReconstructor.h @@ -35,24 +35,26 @@ class PDBHeaderReconstructor { Settings() { - MemberStructExpansion = MemberStructExpansionType::InlineUnnamed; - OutputFile = &std::cout; - TestFile = nullptr; - PaddingMemberPrefix = "Padding_"; - UnnamedTypePrefix = "TAG_UNNAMED_"; - AnonymousStructPrefix = "s"; // DUMMYSTRUCTNAME (up to 6) - AnonymousUnionPrefix = "u"; // DUMMYUNIONNAME (up to 9) - CreatePaddingMembers = true; - ShowOffsets = true; - MicrosoftTypedefs = true; - AllowBitFieldsInUnion = false; - AllowAnonymousDataTypes = true; + MemberStructExpansion = MemberStructExpansionType::InlineUnnamed; + OutputFile = &std::cout; + TestFile = nullptr; + PaddingMemberPrefix = "Padding_"; + BitFieldPaddingMemberPrefix = ""; + UnnamedTypePrefix = "TAG_UNNAMED_"; + AnonymousStructPrefix = "s"; // DUMMYSTRUCTNAME (up to 6) + AnonymousUnionPrefix = "u"; // DUMMYUNIONNAME (up to 9) + CreatePaddingMembers = true; + ShowOffsets = true; + MicrosoftTypedefs = true; + AllowBitFieldsInUnion = false; + AllowAnonymousDataTypes = true; } MemberStructExpansionType MemberStructExpansion; std::ostream* OutputFile; std::ostream* TestFile; std::string PaddingMemberPrefix; + std::string BitFieldPaddingMemberPrefix; std::string UnnamedTypePrefix; std::string SymbolPrefix; std::string SymbolSuffix; @@ -163,6 +165,12 @@ class PDBHeaderReconstructor DWORD PaddingSize ) override; + void + OnPaddingBitFieldField( + const SYMBOL_UDT_FIELD* UdtField, + const SYMBOL_UDT_FIELD* PreviousUdtField + ) override; + private: void Write( diff --git a/Source/PDBReconstructorBase.h b/Source/PDBReconstructorBase.h index 2d55031..cb77efd 100644 --- a/Source/PDBReconstructorBase.h +++ b/Source/PDBReconstructorBase.h @@ -200,4 +200,17 @@ class PDBReconstructorBase { } + + // + // Called when a padding bitfield field should be created. + // + virtual + void + OnPaddingBitFieldField( + const SYMBOL_UDT_FIELD* UdtField, + const SYMBOL_UDT_FIELD* PreviousUdtField + ) + { + + } }; diff --git a/Source/PDBSymbolVisitor.h b/Source/PDBSymbolVisitor.h index b0b33d9..91f2f04 100644 --- a/Source/PDBSymbolVisitor.h +++ b/Source/PDBSymbolVisitor.h @@ -192,7 +192,7 @@ class PDBSymbolVisitor bool HasValue() const { - return FirstUdtFieldBitField != nullptr && + return /*FirstUdtFieldBitField != nullptr &&*/ LastUdtFieldBitField != nullptr; } }; @@ -272,6 +272,11 @@ class PDBSymbolVisitor const SYMBOL_UDT_FIELD* UdtField ); + void + CheckForBitFieldFieldPadding( + const SYMBOL_UDT_FIELD* UdtField + ); + void CheckForAnonymousUnion( const SYMBOL_UDT_FIELD* UdtField @@ -321,14 +326,17 @@ class PDBSymbolVisitor // // - // These two properties are used for padding. + // These three properties are used for padding. // m_SizeOfPreviousUdtField holds the size of the previous // UDT field with respect to nested unnamed and anonymous UDTs. // // m_PreviousUdtField just holds pointer to the previous UDT field. // + // m_PreviousBitFieldField holds pointer to the previous bitfield field. + // DWORD m_SizeOfPreviousUdtField = 0; const SYMBOL_UDT_FIELD* m_PreviousUdtField = nullptr; + const SYMBOL_UDT_FIELD* m_PreviousBitFieldField = nullptr; // // This stack holds information about anonymous UDTs. diff --git a/Source/PDBSymbolVisitor.inl b/Source/PDBSymbolVisitor.inl index 57b2f38..bdef139 100644 --- a/Source/PDBSymbolVisitor.inl +++ b/Source/PDBSymbolVisitor.inl @@ -267,7 +267,7 @@ PDBSymbolVisitor::VisitUdtField( ) { BOOL IsBitFieldMember = UdtField->Bits != 0; - BOOL IsFirstBitFieldMember = IsBitFieldMember && UdtField->BitPosition == 0; + BOOL IsFirstBitFieldMember = IsBitFieldMember && !m_PreviousBitFieldField; // // Push new member context. @@ -293,15 +293,23 @@ PDBSymbolVisitor::VisitUdtField( CheckForAnonymousStruct(UdtField); } + // + // Is this the first bitfield member? + // + if (IsFirstBitFieldMember) { - // - // This is the first bitfield member. - // + BOOL IsFirstBitFieldMemberPadding = UdtField->BitPosition != 0; assert(m_CurrentBitField.HasValue() == false); - m_CurrentBitField.FirstUdtFieldBitField = UdtField; + // + // If first bitfield field is padding, set "FirstUdtFieldBitField" as nullptr. + // This forces creation of the "wrapping" struct even if this bitfield + // has only one NAMED member. + // + + m_CurrentBitField.FirstUdtFieldBitField = IsFirstBitFieldMemberPadding ? nullptr : UdtField; m_CurrentBitField.LastUdtFieldBitField = GetNextUdtFieldWithRespectToBitFields(UdtField) - 1; m_ReconstructVisitor->OnUdtFieldBitFieldBegin( @@ -310,6 +318,15 @@ PDBSymbolVisitor::VisitUdtField( ); } + if (IsBitFieldMember) + { + // + // Handling of unnamed bitfield fields. + // + + CheckForBitFieldFieldPadding(UdtField); + } + // // Dump the field. // @@ -320,6 +337,12 @@ PDBSymbolVisitor::VisitUdtField( m_ReconstructVisitor->OnUdtFieldEnd(UdtField); m_MemberContextStack.pop(); + + // + // Remember this UdtField as a last bitfield field. + // + + m_PreviousBitFieldField = UdtField; } template < @@ -352,6 +375,8 @@ PDBSymbolVisitor::VisitUdtFieldBitFieldEnd( m_CurrentBitField.Clear(); VisitUdtFieldEnd(UdtField); + + m_PreviousBitFieldField = nullptr; } template < @@ -418,6 +443,52 @@ PDBSymbolVisitor::CheckForDataFieldPadding( } } +template < + typename MEMBER_DEFINITION_TYPE +> +void +PDBSymbolVisitor::CheckForBitFieldFieldPadding( + const SYMBOL_UDT_FIELD* UdtField + ) +{ + BOOL WasPreviousBitFieldMember = m_PreviousBitFieldField + ? m_PreviousBitFieldField->Bits != 0 + : FALSE; + + if ( + // + // Checks if the first bitfield field is unnamed: + // struct XYZ + // { + // unsigned : 16; // Unnamed bitfield field! + // unsigned var : 16; + // }; + // + + (UdtField->BitPosition != 0 && !WasPreviousBitFieldMember) || + + // + // Checks if some middle bitfield field is unnamed: + // struct XYZ + // { + // unsigned var1 : 12; + // unsigned : 10; // Unnamed bitfield field! + // unsigned var2 : 12; + // }; + // + + (WasPreviousBitFieldMember && + UdtField->BitPosition != m_PreviousBitFieldField->BitPosition + m_PreviousBitFieldField->Bits) + ) + { + // + // Create padding bitfield field. + // + + m_ReconstructVisitor->OnPaddingBitFieldField(UdtField, m_PreviousBitFieldField); + } +} + template < typename MEMBER_DEFINITION_TYPE >