Skip to content

Commit

Permalink
support unnamed bitfield fields
Browse files Browse the repository at this point in the history
  • Loading branch information
wbenny committed Jan 10, 2019
1 parent 29addda commit c813a99
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 19 deletions.
56 changes: 56 additions & 0 deletions Source/PDBHeaderReconstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
32 changes: 20 additions & 12 deletions Source/PDBHeaderReconstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down
13 changes: 13 additions & 0 deletions Source/PDBReconstructorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
{

}
};
12 changes: 10 additions & 2 deletions Source/PDBSymbolVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class PDBSymbolVisitor
bool
HasValue() const
{
return FirstUdtFieldBitField != nullptr &&
return /*FirstUdtFieldBitField != nullptr &&*/
LastUdtFieldBitField != nullptr;
}
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
81 changes: 76 additions & 5 deletions Source/PDBSymbolVisitor.inl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::VisitUdtField(
)
{
BOOL IsBitFieldMember = UdtField->Bits != 0;
BOOL IsFirstBitFieldMember = IsBitFieldMember && UdtField->BitPosition == 0;
BOOL IsFirstBitFieldMember = IsBitFieldMember && !m_PreviousBitFieldField;

//
// Push new member context.
Expand All @@ -293,15 +293,23 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::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(
Expand All @@ -310,6 +318,15 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::VisitUdtField(
);
}

if (IsBitFieldMember)
{
//
// Handling of unnamed bitfield fields.
//

CheckForBitFieldFieldPadding(UdtField);
}

//
// Dump the field.
//
Expand All @@ -320,6 +337,12 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::VisitUdtField(
m_ReconstructVisitor->OnUdtFieldEnd(UdtField);

m_MemberContextStack.pop();

//
// Remember this UdtField as a last bitfield field.
//

m_PreviousBitFieldField = UdtField;
}

template <
Expand Down Expand Up @@ -352,6 +375,8 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::VisitUdtFieldBitFieldEnd(
m_CurrentBitField.Clear();

VisitUdtFieldEnd(UdtField);

m_PreviousBitFieldField = nullptr;
}

template <
Expand Down Expand Up @@ -418,6 +443,52 @@ PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::CheckForDataFieldPadding(
}
}

template <
typename MEMBER_DEFINITION_TYPE
>
void
PDBSymbolVisitor<MEMBER_DEFINITION_TYPE>::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
>
Expand Down

0 comments on commit c813a99

Please sign in to comment.