Skip to content

Commit

Permalink
add support for sorting, print enums in declaration list
Browse files Browse the repository at this point in the history
  • Loading branch information
wbenny committed Aug 24, 2018
1 parent 7194353 commit 97ec118
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 21 deletions.
35 changes: 29 additions & 6 deletions Source/PDBExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "PDBHeaderReconstructor.h"
#include "PDBSymbolVisitor.h"
#include "PDBSymbolSorter.h"
#include "PDBSymbolSorterAlphabetical.h"
#include "UdtFieldDefinition.h"

#include <iostream>
Expand Down Expand Up @@ -147,6 +148,7 @@ PDBExtractor::PrintUsage()
printf(" -n Print declarations. (T)\n");
printf(" -l Print definitions. (T)\n");
printf(" -z Print #pragma pack directives. (T)\n");
printf(" -y Sort declarations and definitions. (F)\n");
printf("\n");
}

Expand Down Expand Up @@ -354,6 +356,10 @@ PDBExtractor::ParseParameters(
m_Settings.PrintPragmaPack = !OffSwitch;
break;

case 'y':
m_Settings.Sort = !OffSwitch;
break;

default:
throw PDBDumperException(MESSAGE_INVALID_PARAMETERS);
}
Expand All @@ -368,7 +374,14 @@ PDBExtractor::ParseParameters(
&m_Settings.UdtFieldDefinitionSettings
);

m_SymbolSorter = std::make_unique<PDBSymbolSorter>();
if (m_Settings.Sort)
{
m_SymbolSorter = std::make_unique<PDBSymbolSorterAlphabetical>();
}
else
{
m_SymbolSorter = std::make_unique<PDBSymbolSorter>();
}
}

void
Expand Down Expand Up @@ -440,12 +453,22 @@ PDBExtractor::PrintPDBDeclarations()
{
for (auto&& e : m_SymbolSorter->GetSortedSymbols())
{
if (e->Tag == SymTagUDT && !PDB::IsUnnamedSymbol(e))
if (!PDB::IsUnnamedSymbol(e))
{
*m_Settings.PdbHeaderReconstructorSettings.OutputFile
<< PDB::GetUdtKindString(e->u.Udt.Kind)
<< " " << m_HeaderReconstructor->GetCorrectedSymbolName(e) << ";"
<< std::endl;
if (e->Tag == SymTagUDT)
{
*m_Settings.PdbHeaderReconstructorSettings.OutputFile
<< PDB::GetUdtKindString(e->u.Udt.Kind)
<< " " << m_HeaderReconstructor->GetCorrectedSymbolName(e) << ";"
<< std::endl;
}
else if (e->Tag == SymTagEnum)
{
*m_Settings.PdbHeaderReconstructorSettings.OutputFile
<< "enum"
<< " " << m_HeaderReconstructor->GetCorrectedSymbolName(e) << ";"
<< std::endl;
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions Source/PDBExtractor.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include "PDBSymbolSorter.h"
#include "PDBSymbolSorterBase.h"
#include "PDBHeaderReconstructor.h"
#include "PDBSymbolVisitor.h"
#include "UdtFieldDefinition.h"
Expand Down Expand Up @@ -31,6 +31,7 @@ class PDBExtractor
bool PrintDeclarations = true;
bool PrintDefinitions = true;
bool PrintPragmaPack = true;
bool Sort = false;
};

int Run(
Expand Down Expand Up @@ -79,7 +80,7 @@ class PDBExtractor
PDB m_PDB;
Settings m_Settings;

std::unique_ptr<PDBSymbolSorter> m_SymbolSorter;
std::unique_ptr<PDBSymbolSorterBase> m_SymbolSorter;
std::unique_ptr<PDBHeaderReconstructor> m_HeaderReconstructor;
std::unique_ptr<PDBSymbolVisitor<UdtFieldDefinition>> m_SymbolVisitor;
};
18 changes: 5 additions & 13 deletions Source/PDBSymbolSorter.h
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
#pragma once
#include "PDB.h"
#include "PDBSymbolVisitorBase.h"
#include "PDBSymbolSorterBase.h"

#include <cassert>
#include <string>
#include <vector>
#include <map>

enum class ImageArchitecture
{
None,
x86,
x64,
};

class PDBSymbolSorter
: public PDBSymbolVisitorBase
: public PDBSymbolSorterBase
{
public:
std::vector<const SYMBOL*>&
GetSortedSymbols()
GetSortedSymbols() override
{
return m_SortedSymbols;
}

ImageArchitecture
GetImageArchitecture() const
GetImageArchitecture() const override
{
return m_Architecture;
}

void
Clear()
Clear() override
{
ImageArchitecture m_Architecture = ImageArchitecture::None;

Expand Down
161 changes: 161 additions & 0 deletions Source/PDBSymbolSorterAlphabetical.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#pragma once
#include "PDBSymbolSorterBase.h"

#include <cassert>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

class PDBSymbolSorterAlphabetical
: public PDBSymbolSorterBase
{
public:
std::vector<const SYMBOL*>&
GetSortedSymbols() override
{
if (m_Dirty)
{
std::sort(
m_SortedSymbols.begin(),
m_SortedSymbols.end(),
[](const SYMBOL* lhs, const SYMBOL* rhs) {
return strcmp(lhs->Name, rhs->Name) < 0;
});

m_Dirty = false;
}

return m_SortedSymbols;
}

ImageArchitecture
GetImageArchitecture() const override
{
return m_Architecture;
}

void
Clear() override
{
ImageArchitecture m_Architecture = ImageArchitecture::None;

m_VisitedUdts.clear();
m_SortedSymbols.clear();
}

protected:
void
VisitEnumType(
const SYMBOL* Symbol
) override
{
if (HasBeenVisited(Symbol)) return;

AddSymbol(Symbol);
}

void
VisitPointerType(
const SYMBOL* Symbol
) override
{
if (m_Architecture == ImageArchitecture::None)
{
switch (Symbol->Size)
{
case 4:
m_Architecture = ImageArchitecture::x86;
break;

case 8:
m_Architecture = ImageArchitecture::x64;
break;

default:
assert(0);
break;
}
}
}

void
VisitUdt(
const SYMBOL* Symbol
) override
{
if (HasBeenVisited(Symbol)) return;

PDBSymbolVisitorBase::VisitUdt(Symbol);

AddSymbol(Symbol);
}

void
VisitUdtField(
const SYMBOL_UDT_FIELD* UdtField
) override
{
Visit(UdtField->Type);
}

private:
bool
HasBeenVisited(
const SYMBOL* Symbol
)
{
static DWORD UnnamedCounter = 0;

//
// In one PDB there can be more than one symbol
// with same name (and different definitions),
// which would result into redefinitions of types
// during the printing.
//
// Problem is solved by taking into account
// and printing only the first definition of the symbol.
//
// Another solution could be appending a suffix (_1, _2, ...)
// to the symbol names, but then it wouldn't reflect the real names.
// So let's just assume all definitions are same
// and/or the first one is the most correct one.
//
// Also, unnamed symbols must be handled as a special case.
//

std::string Key = Symbol->Name;
if (m_VisitedUdts.find(Key) != m_VisitedUdts.end())
{
return true;
}
else
{
if (PDB::IsUnnamedSymbol(Symbol))
{
Key += std::to_string(++UnnamedCounter);
}

m_VisitedUdts[Key] = Symbol;
return false;
}
}

void
AddSymbol(
const SYMBOL* Symbol
)
{
if (std::find(m_SortedSymbols.begin(), m_SortedSymbols.end(), Symbol) == m_SortedSymbols.end())
{
m_SortedSymbols.push_back(Symbol);
m_Dirty = true;
}
}

ImageArchitecture m_Architecture = ImageArchitecture::None;

std::map<std::string, const SYMBOL*> m_VisitedUdts;
std::vector<const SYMBOL*> m_SortedSymbols;
bool m_Dirty = true;
};
29 changes: 29 additions & 0 deletions Source/PDBSymbolSorterBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include "PDB.h"
#include "PDBSymbolVisitorBase.h"

#include <vector>

class PDBSymbolSorterBase
: public PDBSymbolVisitorBase
{
public:
enum class ImageArchitecture
{
None,
x86,
x64,
};

virtual
std::vector<const SYMBOL*>&
GetSortedSymbols() = 0;

virtual
ImageArchitecture
GetImageArchitecture() const = 0;

virtual
void
Clear() = 0;
};
2 changes: 2 additions & 0 deletions Source/pdbex.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
<ClInclude Include="PDBExtractor.h" />
<ClInclude Include="PDBHeaderReconstructor.h" />
<ClInclude Include="PDBReconstructorBase.h" />
<ClInclude Include="PDBSymbolSorterAlphabetical.h" />
<ClInclude Include="PDBSymbolSorterBase.h" />
<ClInclude Include="PDBSymbolVisitorBase.h" />
<ClInclude Include="PDBSymbolVisitor.h" />
<ClInclude Include="PDBSymbolSorter.h" />
Expand Down
6 changes: 6 additions & 0 deletions Source/pdbex.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
<ClInclude Include="UdtFieldDefinitionBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PDBSymbolSorterAlphabetical.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PDBSymbolSorterBase.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="PDBSymbolVisitor.inl">
Expand Down

0 comments on commit 97ec118

Please sign in to comment.