feat: complete extractsym.
This commit is contained in:
45
ExtractSYM/.clang-format
Normal file
45
ExtractSYM/.clang-format
Normal file
@@ -0,0 +1,45 @@
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AlignOperands: AlignAfterOperator
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: "Yes"
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
ConstructorInitializerIndentWidth: 0
|
||||
IndentWidth: 4
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 2
|
||||
PackConstructorInitializers: CurrentLine
|
||||
PointerAlignment: Left
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
SortIncludes: CaseSensitive
|
||||
9
ExtractSYM/.gitignore
vendored
Normal file
9
ExtractSYM/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# VSCode
|
||||
.vscode
|
||||
|
||||
# XMake
|
||||
.xmake
|
||||
build
|
||||
|
||||
# ClangD
|
||||
.cache
|
||||
1
ExtractSYM/README.md
Normal file
1
ExtractSYM/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# ExtractSYM
|
||||
99
ExtractSYM/src/main.cpp
Normal file
99
ExtractSYM/src/main.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <llvm/DebugInfo/CodeView/CVRecord.h>
|
||||
#include <llvm/DebugInfo/CodeView/SymbolDeserializer.h>
|
||||
#include <llvm/DebugInfo/PDB/IPDBSession.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/NativeSession.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/PDBFile.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/PublicsStream.h>
|
||||
#include <llvm/DebugInfo/PDB/Native/SymbolStream.h>
|
||||
#include <llvm/DebugInfo/PDB/PDB.h>
|
||||
|
||||
#include <argparse/argparse.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <print>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::pdb;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
auto load_args(int argc, char* argv[]) {
|
||||
argparse::ArgumentParser program("extractpdb", "1.0.0");
|
||||
|
||||
struct {
|
||||
std::string m_program_database_path;
|
||||
std::string m_output_path;
|
||||
} args;
|
||||
|
||||
// clang-format off
|
||||
|
||||
program.add_argument("--output", "-o")
|
||||
.help("Path to output symlist.")
|
||||
.store_into(args.m_output_path)
|
||||
.required();
|
||||
|
||||
program.add_argument("pdb")
|
||||
.help("Path to program database.")
|
||||
.store_into(args.m_program_database_path)
|
||||
.required();
|
||||
|
||||
// clang-format on
|
||||
|
||||
program.parse_args(argc, argv);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) try {
|
||||
|
||||
auto args = load_args(argc, argv);
|
||||
|
||||
std::unique_ptr<IPDBSession> pdb_session;
|
||||
if (llvm::pdb::loadDataForPDB(
|
||||
PDB_ReaderType::Native,
|
||||
args.m_program_database_path,
|
||||
pdb_session
|
||||
)) {
|
||||
throw std::runtime_error("Failed to load PDB.");
|
||||
}
|
||||
|
||||
auto native_session = static_cast<NativeSession*>(pdb_session.get());
|
||||
auto& pdb_file = native_session->getPDBFile();
|
||||
|
||||
auto publics_stream = pdb_file.getPDBPublicsStream();
|
||||
if (!publics_stream) {
|
||||
throw std::runtime_error("Failed to get public stream from PDB.");
|
||||
}
|
||||
|
||||
auto publics_symbol_stream = pdb_file.getPDBSymbolStream();
|
||||
if (!publics_symbol_stream) {
|
||||
throw std::runtime_error("Failed to get symbol stream from PDB.");
|
||||
}
|
||||
|
||||
std::ofstream ofs(args.m_output_path);
|
||||
if (!ofs) {
|
||||
throw std::runtime_error("Failed to open output file.");
|
||||
}
|
||||
|
||||
auto publics_symbols =
|
||||
publics_symbol_stream->getSymbolArray().getUnderlyingStream();
|
||||
for (uint32_t offset : publics_stream->getPublicsTable()) {
|
||||
auto cv_symbol = readSymbolFromStream(publics_symbols, offset);
|
||||
auto public_sym32 =
|
||||
SymbolDeserializer::deserializeAs<PublicSym32>(cv_symbol.get());
|
||||
if (!public_sym32) {
|
||||
throw std::runtime_error("Unsupported symbol type.");
|
||||
}
|
||||
|
||||
ofs
|
||||
<< ((public_sym32->Flags & PublicSymFlags::Function)
|
||||
!= PublicSymFlags::None
|
||||
? "Function, "
|
||||
: "Var, ")
|
||||
<< public_sym32->Name.str() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::println("E: {}", e.what());
|
||||
return -1;
|
||||
}
|
||||
22
ExtractSYM/xmake.lua
Normal file
22
ExtractSYM/xmake.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
add_rules('mode.debug', 'mode.release')
|
||||
|
||||
add_requires('llvm')
|
||||
add_requires('argparse 3.1')
|
||||
|
||||
target('extractsym')
|
||||
set_kind('binary')
|
||||
add_files('src/**.cpp')
|
||||
add_includedirs('src')
|
||||
set_warnings('all')
|
||||
set_languages('c23', 'c++23')
|
||||
|
||||
add_packages(
|
||||
'llvm',
|
||||
'argparse'
|
||||
)
|
||||
|
||||
add_links('LLVM')
|
||||
|
||||
if is_mode('debug') then
|
||||
add_defines('DEBUG')
|
||||
end
|
||||
Reference in New Issue
Block a user