mirror of
https://github.com/wbenny/pdbex
synced 2026-06-08 18:13:37 +00:00
add support for sorting, print enums in declaration list
This commit is contained in:
+29
-6
@@ -2,6 +2,7 @@
|
||||
#include "PDBHeaderReconstructor.h"
|
||||
#include "PDBSymbolVisitor.h"
|
||||
#include "PDBSymbolSorter.h"
|
||||
#include "PDBSymbolSorterAlphabetical.h"
|
||||
#include "UdtFieldDefinition.h"
|
||||
|
||||
#include <iostream>
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -354,6 +356,10 @@ PDBExtractor::ParseParameters(
|
||||
m_Settings.PrintPragmaPack = !OffSwitch;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
m_Settings.Sort = !OffSwitch;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw PDBDumperException(MESSAGE_INVALID_PARAMETERS);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "PDBSymbolSorter.h"
|
||||
#include "PDBSymbolSorterBase.h"
|
||||
#include "PDBHeaderReconstructor.h"
|
||||
#include "PDBSymbolVisitor.h"
|
||||
#include "UdtFieldDefinition.h"
|
||||
@@ -31,6 +31,7 @@ class PDBExtractor
|
||||
bool PrintDeclarations = true;
|
||||
bool PrintDefinitions = true;
|
||||
bool PrintPragmaPack = true;
|
||||
bool Sort = false;
|
||||
};
|
||||
|
||||
int Run(
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user