From 5f4a912e30c5ebc13bddd803723d0a0a3f80f596 Mon Sep 17 00:00:00 2001 From: RedbeanW Date: Thu, 27 Feb 2025 23:07:54 +0800 Subject: [PATCH] refactor: new project structure. --- BlobExtractor/.clang-format => .clang-format | 0 AskRVA/.clangd => .clangd.windows | 0 .gitignore | 14 ++ .gitmodules | 3 - AskRVA/.clang-format | 46 ------- AskRVA/.gitignore | 9 -- AskRVA/src/format/input/all.h | 3 - AskRVA/src/format/input/decl_type.cpp | 37 ------ AskRVA/src/format/input/decl_type.h | 55 -------- AskRVA/src/format/input/symbol.h | 20 --- AskRVA/src/format/output/all.cpp | 35 ----- AskRVA/src/format/output/all.h | 33 ----- AskRVA/src/format/output/fakepdb.cpp | 21 --- AskRVA/src/format/output/fakepdb.h | 12 -- AskRVA/src/format/output/makepdb.cpp | 33 ----- AskRVA/src/format/output/makepdb.h | 16 --- AskRVA/src/format/output/text.h | 16 --- AskRVA/xmake.lua | 31 ----- BlobExtractor/.gitignore | 9 -- BlobExtractor/xmake.lua | 14 -- Bootstrap/.gitignore | 5 - DeThunk/.gitignore | 6 - DeThunk/requirements.txt | 0 DeThunk/ruff.toml | 17 --- DumpSYM | 1 - ExtractSYM/.clang-format | 45 ------- ExtractSYM/.gitignore | 9 -- ExtractSYM/xmake.lua | 22 ---- MakePDB/.clang-format | 45 ------- MakePDB/.gitignore | 9 -- MakePDB/src/binary/PDB.h | 53 -------- MakePDB/src/nonstd.h | 6 - MakePDB/src/pch.h | 20 --- MakePDB/src/symbol_data.cpp | 32 ----- MakePDB/src/symbol_data.h | 35 ----- MakePDB/xmake.lua | 25 ---- README.md | 60 ++++++--- AskRVA/README.md => docs/ask-rva.md | 2 +- .../README.md => docs/blob-extractor.md | 0 Bootstrap/README.md => docs/bootstrap.md | 0 DeThunk/README.md => docs/de-thunk.md | 0 docs/dump-sym.md | 38 ++++++ ExtractSYM/README.md => docs/extract-sym.md | 0 MakePDB/README.md => docs/makepdb.md | 0 .../requirements.txt => requirements.txt | 0 Bootstrap/ruff.toml => ruff.toml | 0 {Bootstrap/src => scripts/bootstrap}/main.py | 0 .../dethunk}/header_preprocessor.py | 0 .../dethunk}/header_processor.py | 0 {DeThunk/src => scripts/dethunk}/main.py | 0 {DeThunk/src => scripts/dethunk}/options.py | 0 .../dethunk}/util/cpp_language.py | 0 .../src => scripts/dethunk}/util/string.py | 0 src/data_format/bound_symbol_list.cpp | 55 ++++++++ src/data_format/bound_symbol_list.h | 25 ++++ .../human_readable_symbol_list.cpp | 10 +- src/data_format/human_readable_symbol_list.h | 14 ++ src/data_format/raw_text.cpp | 19 +++ src/data_format/raw_text.h | 14 ++ .../src => src/data_format}/raw_type_data.cpp | 7 +- .../src => src/data_format}/raw_type_data.h | 9 +- src/data_format/type/bound_symbol.h | 33 +++++ src/data_format/type/decl_type.h | 75 +++++++++++ src/data_format/type/typed_symbol.h | 27 ++++ .../data_format/typed_symbol_list.cpp | 25 ++-- src/data_format/typed_symbol_list.h | 23 ++++ src/frontend_action/dump_symbol.cpp | 119 +++++++++++++++++ src/frontend_action/dump_symbol.h | 27 ++++ {AskRVA/src => src}/nonstd.h | 9 +- .../src/binary => src/object_file}/COFF.cpp | 6 +- .../src/binary => src/object_file}/COFF.h | 4 +- .../src/binary => src/object_file}/PDB.cpp | 33 +++-- src/object_file/PDB.h | 53 ++++++++ {AskRVA/src => src}/pch.h | 16 ++- {AskRVA/src => src/tools/askrva}/main.cpp | 53 +++++--- .../src => src/tools/blob-extractor}/main.cpp | 5 - src/tools/dumpsym/plugin.cpp | 9 ++ .../src => src/tools/extractsym}/main.cpp | 3 - {MakePDB/src => src/tools/makepdb}/main.cpp | 24 ++-- {AskRVA/src => src}/util/string.h | 4 +- xmake.lua | 120 ++++++++++++++++++ 81 files changed, 816 insertions(+), 842 deletions(-) rename BlobExtractor/.clang-format => .clang-format (100%) rename AskRVA/.clangd => .clangd.windows (100%) create mode 100644 .gitignore delete mode 100644 .gitmodules delete mode 100644 AskRVA/.clang-format delete mode 100644 AskRVA/.gitignore delete mode 100644 AskRVA/src/format/input/all.h delete mode 100644 AskRVA/src/format/input/decl_type.cpp delete mode 100644 AskRVA/src/format/input/decl_type.h delete mode 100644 AskRVA/src/format/input/symbol.h delete mode 100644 AskRVA/src/format/output/all.cpp delete mode 100644 AskRVA/src/format/output/all.h delete mode 100644 AskRVA/src/format/output/fakepdb.cpp delete mode 100644 AskRVA/src/format/output/fakepdb.h delete mode 100644 AskRVA/src/format/output/makepdb.cpp delete mode 100644 AskRVA/src/format/output/makepdb.h delete mode 100644 AskRVA/src/format/output/text.h delete mode 100644 AskRVA/xmake.lua delete mode 100644 BlobExtractor/.gitignore delete mode 100644 BlobExtractor/xmake.lua delete mode 100644 Bootstrap/.gitignore delete mode 100644 DeThunk/.gitignore delete mode 100644 DeThunk/requirements.txt delete mode 100644 DeThunk/ruff.toml delete mode 160000 DumpSYM delete mode 100644 ExtractSYM/.clang-format delete mode 100644 ExtractSYM/.gitignore delete mode 100644 ExtractSYM/xmake.lua delete mode 100644 MakePDB/.clang-format delete mode 100644 MakePDB/.gitignore delete mode 100644 MakePDB/src/binary/PDB.h delete mode 100644 MakePDB/src/nonstd.h delete mode 100644 MakePDB/src/pch.h delete mode 100644 MakePDB/src/symbol_data.cpp delete mode 100644 MakePDB/src/symbol_data.h delete mode 100644 MakePDB/xmake.lua rename AskRVA/README.md => docs/ask-rva.md (96%) rename BlobExtractor/README.md => docs/blob-extractor.md (100%) rename Bootstrap/README.md => docs/bootstrap.md (100%) rename DeThunk/README.md => docs/de-thunk.md (100%) create mode 100644 docs/dump-sym.md rename ExtractSYM/README.md => docs/extract-sym.md (100%) rename MakePDB/README.md => docs/makepdb.md (100%) rename Bootstrap/requirements.txt => requirements.txt (100%) rename Bootstrap/ruff.toml => ruff.toml (100%) rename {Bootstrap/src => scripts/bootstrap}/main.py (100%) rename {DeThunk/src => scripts/dethunk}/header_preprocessor.py (100%) rename {DeThunk/src => scripts/dethunk}/header_processor.py (100%) rename {DeThunk/src => scripts/dethunk}/main.py (100%) rename {DeThunk/src => scripts/dethunk}/options.py (100%) rename {DeThunk/src => scripts/dethunk}/util/cpp_language.py (100%) rename {DeThunk/src => scripts/dethunk}/util/string.py (100%) create mode 100644 src/data_format/bound_symbol_list.cpp create mode 100644 src/data_format/bound_symbol_list.h rename AskRVA/src/format/output/text.cpp => src/data_format/human_readable_symbol_list.cpp (54%) create mode 100644 src/data_format/human_readable_symbol_list.h create mode 100644 src/data_format/raw_text.cpp create mode 100644 src/data_format/raw_text.h rename {MakePDB/src => src/data_format}/raw_type_data.cpp (91%) rename {MakePDB/src => src/data_format}/raw_type_data.h (77%) create mode 100644 src/data_format/type/bound_symbol.h create mode 100644 src/data_format/type/decl_type.h create mode 100644 src/data_format/type/typed_symbol.h rename AskRVA/src/format/input/symbol.cpp => src/data_format/typed_symbol_list.cpp (50%) create mode 100644 src/data_format/typed_symbol_list.h create mode 100644 src/frontend_action/dump_symbol.cpp create mode 100644 src/frontend_action/dump_symbol.h rename {AskRVA/src => src}/nonstd.h (80%) rename {MakePDB/src/binary => src/object_file}/COFF.cpp (95%) rename {MakePDB/src/binary => src/object_file}/COFF.h (88%) rename {MakePDB/src/binary => src/object_file}/PDB.cpp (79%) create mode 100644 src/object_file/PDB.h rename {AskRVA/src => src}/pch.h (70%) rename {AskRVA/src => src/tools/askrva}/main.cpp (61%) rename {BlobExtractor/src => src/tools/blob-extractor}/main.cpp (96%) create mode 100644 src/tools/dumpsym/plugin.cpp rename {ExtractSYM/src => src/tools/extractsym}/main.cpp (98%) rename {MakePDB/src => src/tools/makepdb}/main.cpp (72%) rename {AskRVA/src => src}/util/string.h (74%) create mode 100644 xmake.lua diff --git a/BlobExtractor/.clang-format b/.clang-format similarity index 100% rename from BlobExtractor/.clang-format rename to .clang-format diff --git a/AskRVA/.clangd b/.clangd.windows similarity index 100% rename from AskRVA/.clangd rename to .clangd.windows diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8943449 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# vscode +.vscode + +# c++/xmake +.xmake +build + +# c++/clangd +.cache +.clangd + +# python +__pycache__ +.venv \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e1eb621..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "DumpSYM"] - path = DumpSYM - url = https://github.com/Redbeanw44602/dumpsym.git diff --git a/AskRVA/.clang-format b/AskRVA/.clang-format deleted file mode 100644 index e0b1f4c..0000000 --- a/AskRVA/.clang-format +++ /dev/null @@ -1,46 +0,0 @@ -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 -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' -ConstructorInitializerIndentWidth: 0 -IndentWidth: 4 -Language: Cpp -MaxEmptyLinesToKeep: 2 -PackConstructorInitializers: CurrentLine -PointerAlignment: Left -TabWidth: 4 -UseTab: Never -SortIncludes: CaseSensitive \ No newline at end of file diff --git a/AskRVA/.gitignore b/AskRVA/.gitignore deleted file mode 100644 index bfbcbbf..0000000 --- a/AskRVA/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# VSCode -.vscode - -# XMake -.xmake -build - -# ClangD -.cache diff --git a/AskRVA/src/format/input/all.h b/AskRVA/src/format/input/all.h deleted file mode 100644 index 461cfab..0000000 --- a/AskRVA/src/format/input/all.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "symbol.h" diff --git a/AskRVA/src/format/input/decl_type.cpp b/AskRVA/src/format/input/decl_type.cpp deleted file mode 100644 index c7ed193..0000000 --- a/AskRVA/src/format/input/decl_type.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "format/input/decl_type.h" - -#include "util/string.h" - -namespace format::input { - -DeclType::DeclType(std::string_view str) { - using namespace util::string; - - // clang-format off - - switch (H(str)) { -#define HSTR(x) \ - case H(#x): \ - m_data = x; \ - break - HSTR(Function); - HSTR(CXXDeductionGuide); - HSTR(CXXMethod); - HSTR(CXXConstructor); - HSTR(CXXConversion); - HSTR(CXXDestructor); - HSTR(Var); - HSTR(Decomposition); - HSTR(ImplicitParam); - HSTR(OMPCapturedExpr); - HSTR(ParamVar); - HSTR(VarTemplateSpecialization); -#undef HSTR - default: - throw std::invalid_argument("Unexpected decl type."); - } - - // clang-format on -} - -} // namespace format::input diff --git a/AskRVA/src/format/input/decl_type.h b/AskRVA/src/format/input/decl_type.h deleted file mode 100644 index b8ba178..0000000 --- a/AskRVA/src/format/input/decl_type.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -namespace format::input { - -class DeclType { -public: - enum Enum { - Function, - CXXDeductionGuide, - CXXMethod, - CXXConstructor, - CXXConversion, - CXXDestructor, - - Var, - Decomposition, - ImplicitParam, - OMPCapturedExpr, - ParamVar, - VarTemplateSpecialization, - - COUNT - }; - - explicit DeclType(Enum value) : m_data(value) {} - explicit DeclType(std::string_view str); - - bool isFunction() const { return m_data >= Function && m_data < Var; } - bool isVar() const { return m_data >= Var && m_data < COUNT; } - - Enum data() const { return m_data; } - - bool operator==(const DeclType& other) const { return m_data == other.m_data; } - -private: - Enum m_data; -}; - -struct Symbol { - std::string m_name; - DeclType m_type; - - bool operator==(const Symbol& other) const { return m_name == other.m_name; } -}; - -} // namespace format::input - -namespace std { - -template <> -struct hash { - size_t operator()(const format::input::Symbol& symbol) const { return hash{}(symbol.m_name); } -}; - -} // namespace std diff --git a/AskRVA/src/format/input/symbol.h b/AskRVA/src/format/input/symbol.h deleted file mode 100644 index 1f6731d..0000000 --- a/AskRVA/src/format/input/symbol.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "format/input/decl_type.h" - -namespace format::input { - -class SymbolListFile { -public: - [[nodiscard]] static SymbolListFile load(std::string_view path); - [[nodiscard]] static SymbolListFile load(const std::vector& path); - - void for_each(const std::function& callback); - -private: - SymbolListFile() = default; - - std::unordered_set m_data; -}; - -} // namespace format::input diff --git a/AskRVA/src/format/output/all.cpp b/AskRVA/src/format/output/all.cpp deleted file mode 100644 index f8f8c24..0000000 --- a/AskRVA/src/format/output/all.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "format/output/all.h" - -#include "format/output/fakepdb.h" -#include "format/output/makepdb.h" -#include "format/output/text.h" - -namespace format::output { - -void DefaultOutputFile::record_failure(std::string_view symbol) { m_failed_symbols.emplace(symbol); } - -void DefaultOutputFile::save_failure(std::string_view path) const { - std::ofstream ofs(path.data()); - if (!ofs) { - throw std::runtime_error("Failed to open save file."); - } - - for (const auto& symbol : m_failed_symbols) { - ofs << symbol << "\n"; - } -} - -std::unique_ptr create(OutputFormat format) { - switch (format) { - case OutputFormat::Text: - return std::make_unique(); - case OutputFormat::FakePDB: - return std::make_unique(); - case OutputFormat::MakePDB: - return std::make_unique(); - default: - throw std::invalid_argument("Invalid output file format."); - } -} - -} // namespace format::output \ No newline at end of file diff --git a/AskRVA/src/format/output/all.h b/AskRVA/src/format/output/all.h deleted file mode 100644 index 772d93f..0000000 --- a/AskRVA/src/format/output/all.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -namespace format { - -enum class OutputFormat { Text, FakePDB, MakePDB }; - -namespace output { - -class IOutputFile { -public: - virtual ~IOutputFile() = default; - - virtual void record(std::string_view symbol, uint64_t rva, bool is_function) = 0; - virtual void save(std::string_view path) const = 0; - - virtual void record_failure(std::string_view symbol) = 0; - virtual void save_failure(std::string_view path) const = 0; -}; - -class DefaultOutputFile : public IOutputFile { -public: - void record_failure(std::string_view symbol) override; - void save_failure(std::string_view path) const override; - -protected: - std::unordered_set m_failed_symbols; -}; - -std::unique_ptr create(OutputFormat format); - -} // namespace output - -} // namespace format diff --git a/AskRVA/src/format/output/fakepdb.cpp b/AskRVA/src/format/output/fakepdb.cpp deleted file mode 100644 index 1c540d2..0000000 --- a/AskRVA/src/format/output/fakepdb.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "format/output/fakepdb.h" - -#include - -namespace format::output { - -void OutputFakePDBFile::save(std::string_view path) const { - std::ofstream ofs(path.data()); - if (!ofs) { - throw std::runtime_error("Failed to open save file."); - } - - nlohmann::json data; - for (const auto& [symbol, rva] : m_symbol_rva_map) { - data[symbol] = std::format("{:#x}", rva); - } - - ofs << data.dump(4); -} - -} // namespace format::output diff --git a/AskRVA/src/format/output/fakepdb.h b/AskRVA/src/format/output/fakepdb.h deleted file mode 100644 index 1828526..0000000 --- a/AskRVA/src/format/output/fakepdb.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "format/output/text.h" - -namespace format::output { - -class OutputFakePDBFile : public OutputTextFile { -public: - void save(std::string_view path) const override; -}; - -} // namespace format::output diff --git a/AskRVA/src/format/output/makepdb.cpp b/AskRVA/src/format/output/makepdb.cpp deleted file mode 100644 index 7c73813..0000000 --- a/AskRVA/src/format/output/makepdb.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "format/output/makepdb.h" - -#include - -namespace format::output { - -void OutputMakePDBFile::record(std::string_view symbol, uint64_t rva, bool is_function) { - m_records.emplace(std::string(symbol), rva, is_function); -} - -void OutputMakePDBFile::save(std::string_view path) const { - std::ofstream ofs(path.data()); - if (!ofs) { - throw std::runtime_error("Failed to open save file."); - } - - nlohmann::json data; - - // MakePDB - Format V1 - data["version"] = 1; - - for (const auto& [symbol, rva, is_fun] : m_records) { - data["data"].emplace_back(nlohmann::json{ - {"symbol", symbol}, - {"rva", rva }, - {"is_function", is_fun} - }); - } - - ofs << data.dump(4); -} - -} // namespace format::output diff --git a/AskRVA/src/format/output/makepdb.h b/AskRVA/src/format/output/makepdb.h deleted file mode 100644 index f372c7b..0000000 --- a/AskRVA/src/format/output/makepdb.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "format/output/all.h" - -namespace format::output { - -class OutputMakePDBFile : public DefaultOutputFile { -public: - void record(std::string_view symbol, uint64_t rva, bool is_function) override; - void save(std::string_view path) const override; - -private: - std::unordered_set> m_records; -}; - -} // namespace format::output diff --git a/AskRVA/src/format/output/text.h b/AskRVA/src/format/output/text.h deleted file mode 100644 index f080878..0000000 --- a/AskRVA/src/format/output/text.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "format/output/all.h" - -namespace format::output { - -class OutputTextFile : public DefaultOutputFile { -public: - void record(std::string_view symbol, uint64_t rva, bool is_function) override; - void save(std::string_view path) const override; - -protected: - std::unordered_map m_symbol_rva_map; -}; - -} // namespace format::output diff --git a/AskRVA/xmake.lua b/AskRVA/xmake.lua deleted file mode 100644 index ff37ff1..0000000 --- a/AskRVA/xmake.lua +++ /dev/null @@ -1,31 +0,0 @@ -add_rules('mode.debug', 'mode.release') - -set_allowedplats('windows') -set_allowedarchs('x64') - -add_repositories('liteldev-repo https://github.com/LiteLDev/xmake-repo.git') - --- from xmake-repo -add_requires('argparse 3.1') -add_requires('nlohmann_json 3.11.3') - --- from liteldev-repo -add_requires('preloader 1.12.0') - -target('askrva') - set_kind('binary') - add_files('src/**.cpp') - add_includedirs('src') - set_warnings('all') - set_languages('c23', 'c++23') - set_pcxxheader('src/pch.h') - - add_packages( - 'argparse', - 'nlohmann_json', - 'preloader' - ) - - if is_mode('debug') then - add_defines('DEBUG') - end diff --git a/BlobExtractor/.gitignore b/BlobExtractor/.gitignore deleted file mode 100644 index bfbcbbf..0000000 --- a/BlobExtractor/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# VSCode -.vscode - -# XMake -.xmake -build - -# ClangD -.cache diff --git a/BlobExtractor/xmake.lua b/BlobExtractor/xmake.lua deleted file mode 100644 index b4a07de..0000000 --- a/BlobExtractor/xmake.lua +++ /dev/null @@ -1,14 +0,0 @@ -add_rules('mode.debug', 'mode.release') - -add_requires('xxhash') - -target('blob-extractor') - set_kind('binary') - add_files('src/**.cpp') - add_includedirs('src') - set_warnings('all') - set_languages('c23', 'c++23') - - if is_mode('debug') then - add_defines('DEBUG') - end diff --git a/Bootstrap/.gitignore b/Bootstrap/.gitignore deleted file mode 100644 index cae76cf..0000000 --- a/Bootstrap/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Python -.venv - -# VSCode -.vscode diff --git a/DeThunk/.gitignore b/DeThunk/.gitignore deleted file mode 100644 index aad0440..0000000 --- a/DeThunk/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Python -__pycache__ -.venv - -# VSCode -.vscode diff --git a/DeThunk/requirements.txt b/DeThunk/requirements.txt deleted file mode 100644 index e69de29..0000000 diff --git a/DeThunk/ruff.toml b/DeThunk/ruff.toml deleted file mode 100644 index 8f743f3..0000000 --- a/DeThunk/ruff.toml +++ /dev/null @@ -1,17 +0,0 @@ -# Same as Black. -line-length = 100 -indent-width = 4 - -# Assume Python 3.12 -target-version = "py312" - -[lint] -# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. -# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or -# McCabe complexity (`C901`) by default. -select = ["E", "F", "W"] -ignore = ["E501"] - -[format] -# Like Black, use double quotes for strings. -quote-style = "single" diff --git a/DumpSYM b/DumpSYM deleted file mode 160000 index 6cf0947..0000000 --- a/DumpSYM +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6cf09473085caf602083c179e3c6d6cf7d68c694 diff --git a/ExtractSYM/.clang-format b/ExtractSYM/.clang-format deleted file mode 100644 index d3ead11..0000000 --- a/ExtractSYM/.clang-format +++ /dev/null @@ -1,45 +0,0 @@ -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 diff --git a/ExtractSYM/.gitignore b/ExtractSYM/.gitignore deleted file mode 100644 index bfbcbbf..0000000 --- a/ExtractSYM/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# VSCode -.vscode - -# XMake -.xmake -build - -# ClangD -.cache diff --git a/ExtractSYM/xmake.lua b/ExtractSYM/xmake.lua deleted file mode 100644 index 14a48ef..0000000 --- a/ExtractSYM/xmake.lua +++ /dev/null @@ -1,22 +0,0 @@ -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 diff --git a/MakePDB/.clang-format b/MakePDB/.clang-format deleted file mode 100644 index d3ead11..0000000 --- a/MakePDB/.clang-format +++ /dev/null @@ -1,45 +0,0 @@ -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 diff --git a/MakePDB/.gitignore b/MakePDB/.gitignore deleted file mode 100644 index bfbcbbf..0000000 --- a/MakePDB/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# VSCode -.vscode - -# XMake -.xmake -build - -# ClangD -.cache diff --git a/MakePDB/src/binary/PDB.h b/MakePDB/src/binary/PDB.h deleted file mode 100644 index d205778..0000000 --- a/MakePDB/src/binary/PDB.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "binary/COFF.h" - -#include "raw_type_data.h" -#include "symbol_data.h" - -#include -#include - -namespace makepdb::binary { - -class PDB { -public: - using OwningCOFF = std::unique_ptr; - using OwningSymbolData = std::unique_ptr; - using OwningRawTypeData = std::unique_ptr; - - explicit PDB(); - - void set_coff_object(OwningCOFF coff_object) { - m_owning_coff = std::move(coff_object); - m_image_base = m_owning_coff->get_owning_coff().getImageBase(); - } - - void set_symbol_data(OwningSymbolData symbol_data) { - m_owning_symbol_data = std::move(symbol_data); - } - void set_raw_type_data(OwningRawTypeData raw_type_data) { - m_owning_raw_type_data = std::move(raw_type_data); - } - - void write(std::string_view path); - -private: - void build(); - - inline void build_Info(); - inline void build_DBI(); - inline void build_TPI(); - inline void build_GSI(); - - OwningCOFF m_owning_coff; - OwningSymbolData m_owning_symbol_data; - OwningRawTypeData m_owning_raw_type_data; - - uint64_t m_image_base; - - BumpPtrAllocator m_allocator; - pdb::PDBFileBuilder m_builder; -}; - -} // namespace makepdb::binary diff --git a/MakePDB/src/nonstd.h b/MakePDB/src/nonstd.h deleted file mode 100644 index 3f7beff..0000000 --- a/MakePDB/src/nonstd.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -template -constexpr auto static_unique_ptr_cast(std::unique_ptr&& F) { - return std::unique_ptr(static_cast(F.release())); -} diff --git a/MakePDB/src/pch.h b/MakePDB/src/pch.h deleted file mode 100644 index 3d22bcc..0000000 --- a/MakePDB/src/pch.h +++ /dev/null @@ -1,20 +0,0 @@ - -// Work on llvm namespace. - -namespace llvm {} -using namespace llvm; - -// Standard Libraries - -#include -#include - -#include -#include - -#include -#include - -// Helper - -#include "nonstd.h" diff --git a/MakePDB/src/symbol_data.cpp b/MakePDB/src/symbol_data.cpp deleted file mode 100644 index aea1002..0000000 --- a/MakePDB/src/symbol_data.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "symbol_data.h" - -#include - -namespace makepdb { - -SymbolData::SymbolData(std::string_view path) { - std::ifstream ifs(path.data()); - if (!ifs) { - throw std::runtime_error("Failed to open data path."); - } - - auto data = nlohmann::json::parse(ifs); - if (data["version"] != 1) { - throw std::runtime_error("Unsupported data version."); - } - - for (const auto& entity : data["data"]) { - m_entities.emplace(SymbolDataEntity{ - entity["symbol"], - entity["rva"], - entity["is_function"] - }); - } -} - -void SymbolData::for_each(const std::function callback -) const { - for (const auto& entity : m_entities) callback(entity); -} - -} // namespace makepdb diff --git a/MakePDB/src/symbol_data.h b/MakePDB/src/symbol_data.h deleted file mode 100644 index 5f41cd6..0000000 --- a/MakePDB/src/symbol_data.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -namespace makepdb { - -struct SymbolDataEntity { - std::string symbol_name; - uint64_t rva; - bool is_function; - - bool operator==(const SymbolDataEntity& other) const { - return symbol_name == other.symbol_name && rva == other.rva - && is_function == other.is_function; - } - - struct Hash { - size_t operator()(const SymbolDataEntity entity) const { - size_t h1 = std::hash{}(entity.symbol_name); - size_t h2 = std::hash{}(entity.rva); - size_t h3 = std::hash{}(entity.is_function); - return h1 ^ (h2 << 1) ^ (h3 << 2); - } - }; -}; - -class SymbolData { -public: - explicit SymbolData(std::string_view path); - - void for_each(const std::function callback) const; - -private: - std::unordered_set m_entities; -}; - -} // namespace makepdb diff --git a/MakePDB/xmake.lua b/MakePDB/xmake.lua deleted file mode 100644 index 57bb80c..0000000 --- a/MakePDB/xmake.lua +++ /dev/null @@ -1,25 +0,0 @@ -add_rules('mode.debug', 'mode.release') - -add_requires('llvm') -add_requires('nlohmann_json 3.11.3') -add_requires('argparse 3.1') - -target('makepdb') - set_kind('binary') - add_files('src/**.cpp') - add_includedirs('src') - set_warnings('all') - set_languages('c23', 'c++23') - set_pcxxheader('src/pch.h') - - add_packages( - 'llvm', - 'nlohmann_json', - 'argparse' - ) - - add_links('LLVM') - - if is_mode('debug') then - add_defines('DEBUG') - end diff --git a/README.md b/README.md index 1698d5a..325125b 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,78 @@ # DebugInfo + This repository regenerates debug information (like PDB) from LeviLamina's public data. ## Background - - After 1.21.3.01, Mojang removed debug information from BDS. - - Mojang no longer provides any debugging information (both server and client) to the community. - - Mojang has an agreement with LiteLDev to provide them with debug data. - - LiteLDev generates header files and obfuscated symbol to RVA lookup tables from debug data and provides them to the community. + +- After 1.21.3.01, Mojang removed debug information from BDS. +- Mojang no longer provides any debugging information (both server and client) to the community. +- Mojang has an agreement with LiteLDev to provide them with debug data. +- LiteLDev generates header files and obfuscated symbol to RVA lookup tables from debug data and provides them to the community. ### Problems caused by Mojang's collaboration with LiteLDev - - Mojang's collaboration with LiteLDev is opaque and we have no idea what they do. - - LiteLDev has completed its monopoly, and there will no longer be a second mod loader in the community. - - Due to the obfuscated format, the community can no longer reverse engineer BDS. + +- Mojang's collaboration with LiteLDev is opaque and we have no idea what they do. +- LiteLDev has completed its monopoly, and there will no longer be a second mod loader in the community. +- Due to the obfuscated format, the community can no longer reverse engineer BDS. ### Header files, obfuscation format and security - - LeviLamina's design necessitates that they publish header files. - - The header file contains all the declaration information so that symbols can be generated. - - The RVA of the corresponding symbol can be extracted from the obfuscated format at runtime. - - The obfuscated format is actually a carrier of the complete "symbol table", which used to be PDB/DWARF. + +- LeviLamina's design necessitates that they publish header files. +- The header file contains all the declaration information so that symbols can be generated. +- The RVA of the corresponding symbol can be extracted from the obfuscated format at runtime. +- The obfuscated format is actually a carrier of the complete "symbol table", which used to be PDB/DWARF. ## Tool for restoring original DebugInfo from obfuscated format + > [!NOTE] > LiteLDev has not yet released bedrock_runtime_data/magicblob for the Linux server. They are dethunk, dumpsym, askrva and makepdb. Each tool is in a directory with the same name as it, and also has a README to help you use it. In short, the PDB is generated by the following steps: - - Preprocess the header files published by LiteLDev by dethunk. + +- Preprocess the header files published by LiteLDev by dethunk. + ``` python main.py {HEADER_PROJECT_DIR}/src ``` - - Compile the header file and load the dumpsym plugin in the compilation parameters. + +- Compile the header file and load the dumpsym plugin in the compilation parameters. + ``` xmake f -c -p windows -a x64 -m release --sdk=/opt/msvc --cxflags="-fplugin=/path/to/libdumpsym.so -fplugin-arg-dumpsym-record-decl-name" --toolchain=clang xmake -v ``` - - Find the generated symbols file. + +- Find the generated symbols file. + ``` {HEADER_PROJECT_DIR}/build/.objs/bdsheader/windows/x64/release/test/__cpp_main.cpp.cpp.symbols ``` - - Generate symbol table using askrva. + +- Generate symbol table using askrva. + ``` ./askrva __cpp_main.cpp.cpp.symbols --output succeed.json --output-failed failed.txt --output-format=makepdb ``` - - Generate PDB using makepdb. + +- Generate PDB using makepdb. + ``` ./makepdb --program bedrock_server.exe --symbol-data succeed.json --output bedrock_server.pdb ``` ## TODO - - [ ] Tap into more available symbols. - - [ ] Fully open source HeaderGen. - - [ ] Bootstrap. - - [ ] Opti project structure. + +- [ ] Tap into more available symbols. +- [ ] Fully open source HeaderGen. +- [ ] Bootstrap. ## Be with us + Our vision is to build an open and inclusive Minecraft: Bedrock Edition ecosystem. - - [https://t.me/bdsplugins](https://t.me/s/bdsplugins) + +- [https://t.me/bdsplugins](https://t.me/s/bdsplugins) ## LICENSE + All tools are open source under the MIT license. diff --git a/AskRVA/README.md b/docs/ask-rva.md similarity index 96% rename from AskRVA/README.md rename to docs/ask-rva.md index e7dc7e3..f23be08 100644 --- a/AskRVA/README.md +++ b/docs/ask-rva.md @@ -18,7 +18,7 @@ known as magicblob), PreLoader no longer handles PDB. The source code in the cur ### Usage -- --output-format can be `auto` / `txt` / `fakepdb` / `makepdb` +- --output-format can be `auto` / `txt` / `makepdb` ``` Usage: askrva [--help] [--version] --output VAR [--output-failed VAR] [--output-format VAR] path diff --git a/BlobExtractor/README.md b/docs/blob-extractor.md similarity index 100% rename from BlobExtractor/README.md rename to docs/blob-extractor.md diff --git a/Bootstrap/README.md b/docs/bootstrap.md similarity index 100% rename from Bootstrap/README.md rename to docs/bootstrap.md diff --git a/DeThunk/README.md b/docs/de-thunk.md similarity index 100% rename from DeThunk/README.md rename to docs/de-thunk.md diff --git a/docs/dump-sym.md b/docs/dump-sym.md new file mode 100644 index 0000000..5134279 --- /dev/null +++ b/docs/dump-sym.md @@ -0,0 +1,38 @@ +# DumpSYM + +Sometimes, we need to extract symbols from declarations. So this compiler plugin was born. + +### Build + +> As far as I know, there are some problems with the clang plugin executing under Windows, so I recommend that all operations be performed under Linux. + +- Building llvm will consume a lot of time and resources, it is recommended to pre-install llvm from your system package manager, xmake can detect system packages. +- Run `xmake` to build. + +### Usage + +Simply pass `-fplugin=...` to clang and the plugin will run automatically. + +#### Optional Arguments + +- `record-decl-name` - Add the name of the Decl in the output, reference: [FunctionDecl](https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html), [VarDecl](https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html) + +> [!NOTE] +> Because LLVM is used, both ItaniumABI and MicrosoftABI are supported. + +- Example: + +``` +$ clang++ -fplugin=/path/to/plugin/libdumpsym.so -fplugin-arg-dumpsym-record-decl-name test.cpp +``` + +- The result will be generated in the `.symbols` file + +``` +$ cat test.cpp.symbols +Function, main +CXXDestructor, ??_DThreadPool@OS@@QEAAXXZ +CXXConstructor, ??0SpinLockImpl@@QEAA@AEBV0@@Z +CXXMethod, ??4SpinLockImpl@@QEAAAEAV0@AEBV0@@Z +Var, ?Low@OSThreadPriority@Threading@Bedrock@@2V123@B +``` diff --git a/ExtractSYM/README.md b/docs/extract-sym.md similarity index 100% rename from ExtractSYM/README.md rename to docs/extract-sym.md diff --git a/MakePDB/README.md b/docs/makepdb.md similarity index 100% rename from MakePDB/README.md rename to docs/makepdb.md diff --git a/Bootstrap/requirements.txt b/requirements.txt similarity index 100% rename from Bootstrap/requirements.txt rename to requirements.txt diff --git a/Bootstrap/ruff.toml b/ruff.toml similarity index 100% rename from Bootstrap/ruff.toml rename to ruff.toml diff --git a/Bootstrap/src/main.py b/scripts/bootstrap/main.py similarity index 100% rename from Bootstrap/src/main.py rename to scripts/bootstrap/main.py diff --git a/DeThunk/src/header_preprocessor.py b/scripts/dethunk/header_preprocessor.py similarity index 100% rename from DeThunk/src/header_preprocessor.py rename to scripts/dethunk/header_preprocessor.py diff --git a/DeThunk/src/header_processor.py b/scripts/dethunk/header_processor.py similarity index 100% rename from DeThunk/src/header_processor.py rename to scripts/dethunk/header_processor.py diff --git a/DeThunk/src/main.py b/scripts/dethunk/main.py similarity index 100% rename from DeThunk/src/main.py rename to scripts/dethunk/main.py diff --git a/DeThunk/src/options.py b/scripts/dethunk/options.py similarity index 100% rename from DeThunk/src/options.py rename to scripts/dethunk/options.py diff --git a/DeThunk/src/util/cpp_language.py b/scripts/dethunk/util/cpp_language.py similarity index 100% rename from DeThunk/src/util/cpp_language.py rename to scripts/dethunk/util/cpp_language.py diff --git a/DeThunk/src/util/string.py b/scripts/dethunk/util/string.py similarity index 100% rename from DeThunk/src/util/string.py rename to scripts/dethunk/util/string.py diff --git a/src/data_format/bound_symbol_list.cpp b/src/data_format/bound_symbol_list.cpp new file mode 100644 index 0000000..8bfb2ed --- /dev/null +++ b/src/data_format/bound_symbol_list.cpp @@ -0,0 +1,55 @@ +#include "data_format/bound_symbol_list.h" + +#include + +namespace di::data_format { + +constexpr int BOUND_SYMBOL_LIST_FORMAT_VERSION = 1; + +BoundSymbolList::BoundSymbolList(std::string_view path) { + std::ifstream ifs(path.data()); + if (!ifs) { + throw std::runtime_error("Failed to open data path."); + } + + auto data = nlohmann::json::parse(ifs); + if (data["version"] != BOUND_SYMBOL_LIST_FORMAT_VERSION) { + throw std::runtime_error("Unsupported data version."); + } + + for (const auto& entity : data["data"]) { + m_entities.emplace( + BoundSymbol{entity["symbol"], entity["rva"], entity["is_function"]} + ); + } +} + +void BoundSymbolList::record( + std::string_view symbol, + uint64_t rva, + bool is_function +) { + m_entities.emplace(BoundSymbol{std::string(symbol), rva, is_function}); +} + +void BoundSymbolList::write_to(const std::string& path) const { + std::ofstream ofs(path); + if (!ofs) { + throw std::runtime_error("Failed to open file!"); + } + + nlohmann::json data; + + data["version"] = BOUND_SYMBOL_LIST_FORMAT_VERSION; + for (const auto& entity : m_entities) { + data["data"].emplace_back(nlohmann::json{ + {"symbol", entity.m_symbol_name}, + {"rva", entity.m_rva }, + {"is_function", entity.m_is_function} + }); + } + + ofs << data.dump(4); +} + +} // namespace di::data_format diff --git a/src/data_format/bound_symbol_list.h b/src/data_format/bound_symbol_list.h new file mode 100644 index 0000000..c616764 --- /dev/null +++ b/src/data_format/bound_symbol_list.h @@ -0,0 +1,25 @@ +#pragma once + +#include "data_format/type/bound_symbol.h" + +namespace di::data_format { + +class BoundSymbolList { +public: + using for_each_callback_t = std::function; + + explicit BoundSymbolList() = default; + explicit BoundSymbolList(std::string_view path); + + void record(std::string_view symbol, uint64_t rva, bool is_function); + void write_to(const std::string& path) const; + + constexpr void for_each(const for_each_callback_t& callback) const { + for (const auto& entity : m_entities) callback(entity); + } + +private: + std::unordered_set m_entities; +}; + +} // namespace di::data_format diff --git a/AskRVA/src/format/output/text.cpp b/src/data_format/human_readable_symbol_list.cpp similarity index 54% rename from AskRVA/src/format/output/text.cpp rename to src/data_format/human_readable_symbol_list.cpp index 12d76e2..36d53f9 100644 --- a/AskRVA/src/format/output/text.cpp +++ b/src/data_format/human_readable_symbol_list.cpp @@ -1,12 +1,12 @@ -#include "format/output/text.h" +#include "data_format/human_readable_symbol_list.h" -namespace format::output { +namespace di::data_format { -void OutputTextFile::record(std::string_view symbol, uint64_t rva, bool is_function) { +void HumanReadableSymbolList::record(std::string_view symbol, uint64_t rva) { m_symbol_rva_map.try_emplace(std::string(symbol), rva); } -void OutputTextFile::save(std::string_view path) const { +void HumanReadableSymbolList::write_to(std::string_view path) const { std::ofstream ofs(path.data()); if (!ofs) { throw std::runtime_error("Failed to open save file."); @@ -17,4 +17,4 @@ void OutputTextFile::save(std::string_view path) const { } } -} // namespace format::output +} // namespace di::data_format diff --git a/src/data_format/human_readable_symbol_list.h b/src/data_format/human_readable_symbol_list.h new file mode 100644 index 0000000..6318d07 --- /dev/null +++ b/src/data_format/human_readable_symbol_list.h @@ -0,0 +1,14 @@ +#pragma once + +namespace di::data_format { + +class HumanReadableSymbolList { +public: + void record(std::string_view symbol, uint64_t rva); + void write_to(std::string_view path) const; + +protected: + std::unordered_map m_symbol_rva_map; +}; + +} // namespace di::data_format diff --git a/src/data_format/raw_text.cpp b/src/data_format/raw_text.cpp new file mode 100644 index 0000000..98a6611 --- /dev/null +++ b/src/data_format/raw_text.cpp @@ -0,0 +1,19 @@ +#include "data_format/raw_text.h" + +namespace di::data_format { + +void RawText::record(std::string_view content) { + m_data += content; + m_data += '\n'; +} + +void RawText::write_to(std::string_view path) const { + std::ofstream ofs(path.data()); + if (!ofs) { + throw std::runtime_error("Failed to open save file."); + } + + ofs << m_data; +} + +} // namespace di::data_format diff --git a/src/data_format/raw_text.h b/src/data_format/raw_text.h new file mode 100644 index 0000000..11b6a0a --- /dev/null +++ b/src/data_format/raw_text.h @@ -0,0 +1,14 @@ +#pragma once + +namespace di::data_format { + +class RawText { +public: + void record(std::string_view line); + void write_to(std::string_view path) const; + +private: + std::string m_data; +}; + +} // namespace di::data_format diff --git a/MakePDB/src/raw_type_data.cpp b/src/data_format/raw_type_data.cpp similarity index 91% rename from MakePDB/src/raw_type_data.cpp rename to src/data_format/raw_type_data.cpp index 1faaca8..e179729 100644 --- a/MakePDB/src/raw_type_data.cpp +++ b/src/data_format/raw_type_data.cpp @@ -1,5 +1,6 @@ -#include "raw_type_data.h" +#include "data_format/raw_type_data.h" +#include #include #include #include @@ -9,7 +10,7 @@ using namespace llvm::pdb; -namespace makepdb { +namespace di::data_format { RawTypeData::RawTypeData(std::string_view path) : m_storaged_TPI(m_allocator), @@ -51,4 +52,4 @@ RawTypeData::RawTypeData(std::string_view path) } } -} // namespace makepdb +} // namespace di::data_format diff --git a/MakePDB/src/raw_type_data.h b/src/data_format/raw_type_data.h similarity index 77% rename from MakePDB/src/raw_type_data.h rename to src/data_format/raw_type_data.h index 741ec0f..57fadec 100644 --- a/MakePDB/src/raw_type_data.h +++ b/src/data_format/raw_type_data.h @@ -1,13 +1,12 @@ #pragma once #include -#include -namespace makepdb { +namespace di::data_format { class RawTypeData { public: - using ForEachTpiCallback = + using for_each_callback_t = std::function; enum TypedStream { TPI, IPI }; @@ -15,7 +14,7 @@ public: explicit RawTypeData(std::string_view path); template - void for_each(const ForEachTpiCallback& callback) /*const*/ { + void for_each(const for_each_callback_t& callback) /*const*/ { if constexpr (Stream == TPI) { return m_storaged_TPI.ForEachRecord(callback); } @@ -31,4 +30,4 @@ private: codeview::MergingTypeTableBuilder m_storaged_IPI; }; -} // namespace makepdb +} // namespace di::data_format diff --git a/src/data_format/type/bound_symbol.h b/src/data_format/type/bound_symbol.h new file mode 100644 index 0000000..42494fa --- /dev/null +++ b/src/data_format/type/bound_symbol.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace di { + +struct BoundSymbol { + std::string m_symbol_name; + uint64_t m_rva; + bool m_is_function; + + bool operator==(const BoundSymbol& other) const { + return m_symbol_name == other.m_symbol_name && m_rva == other.m_rva + && m_is_function == other.m_is_function; + } +}; + +} // namespace di + +namespace std { + +template <> +struct hash { + constexpr size_t operator()(const di::BoundSymbol& symbol) const { + size_t seed = 0; + boost::hash_combine(seed, symbol.m_symbol_name); + boost::hash_combine(seed, symbol.m_rva); + boost::hash_combine(seed, symbol.m_is_function); + return seed; + } +}; + +} // namespace std diff --git a/src/data_format/type/decl_type.h b/src/data_format/type/decl_type.h new file mode 100644 index 0000000..b9dc1b6 --- /dev/null +++ b/src/data_format/type/decl_type.h @@ -0,0 +1,75 @@ +#pragma once + +#include "util/string.h" + +namespace di { + +class DeclType { +public: + enum Enum { + Function, + CXXDeductionGuide, + CXXMethod, + CXXConstructor, + CXXConversion, + CXXDestructor, + + Var, + Decomposition, + ImplicitParam, + OMPCapturedExpr, + ParamVar, + VarTemplateSpecialization, + + COUNT + }; + + constexpr explicit DeclType(Enum value) : m_data(value) {} + constexpr explicit DeclType(std::string_view str) { + using namespace util::string; + + // clang-format off + + switch (H(str)) { + #define HSTR(x) \ + case H(#x): \ + m_data = x; \ + break + HSTR(Function); + HSTR(CXXDeductionGuide); + HSTR(CXXMethod); + HSTR(CXXConstructor); + HSTR(CXXConversion); + HSTR(CXXDestructor); + HSTR(Var); + HSTR(Decomposition); + HSTR(ImplicitParam); + HSTR(OMPCapturedExpr); + HSTR(ParamVar); + HSTR(VarTemplateSpecialization); + #undef HSTR + default: + throw std::invalid_argument("Unexpected decl type."); + } + + // clang-format on + } + + constexpr bool is_function() const { + return m_data >= Function && m_data < Var; + } + constexpr bool is_variable() const { + return m_data >= Var && m_data < COUNT; + } + + constexpr Enum data() const { return m_data; } + + constexpr bool operator==(const DeclType& other) const { + return m_data == other.m_data; + } + +private: + Enum m_data; +}; + +} // namespace di diff --git a/src/data_format/type/typed_symbol.h b/src/data_format/type/typed_symbol.h new file mode 100644 index 0000000..046c31c --- /dev/null +++ b/src/data_format/type/typed_symbol.h @@ -0,0 +1,27 @@ +#pragma once + +#include "data_format/type/decl_type.h" + +namespace di { + +struct TypedSymbol { + std::string m_name; + DeclType m_type; + + constexpr bool operator==(const TypedSymbol& other) const { + return m_name == other.m_name; + } +}; + +} // namespace di + +namespace std { + +template <> +struct hash { + constexpr size_t operator()(const di::TypedSymbol& symbol) const { + return std::hash{}(symbol.m_name); + } +}; + +} // namespace std \ No newline at end of file diff --git a/AskRVA/src/format/input/symbol.cpp b/src/data_format/typed_symbol_list.cpp similarity index 50% rename from AskRVA/src/format/input/symbol.cpp rename to src/data_format/typed_symbol_list.cpp index b8a913f..0d3880d 100644 --- a/AskRVA/src/format/input/symbol.cpp +++ b/src/data_format/typed_symbol_list.cpp @@ -1,12 +1,8 @@ -#include "format/input/symbol.h" +#include "data_format/typed_symbol_list.h" -namespace format::input { - -SymbolListFile SymbolListFile::load(std::string_view path) { return load(std::vector{path.data()}); } - -SymbolListFile SymbolListFile::load(const std::vector& paths) { - SymbolListFile result; +namespace di::data_format { +TypedSymbolList::TypedSymbolList(const std::vector& paths) { for (const auto& path : paths) { std::ifstream ifs(path.data()); if (!ifs) { @@ -20,24 +16,19 @@ SymbolListFile SymbolListFile::load(const std::vector& paths) { auto separator_pos = line.find(", "); if (separator_pos == std::string::npos) { throw std::runtime_error( - "Symbol data is not included declType, please re-generate symlist file with -record-decl-name." + "Symbol data is not included declType, please re-generate " + "symlist file with -record-decl-name." ); } auto declType_s = line.substr(0, separator_pos); auto symbol = line.substr(separator_pos + 2); - result.m_data.emplace(symbol, DeclType(declType_s)); + m_data.emplace(symbol, DeclType(declType_s)); } - std::println("Read {} symbols from dumped symlist.", result.m_data.size()); + std::println("Read {} symbols from dumped symlist.", m_data.size()); } - - return result; } -void SymbolListFile::for_each(const std::function& callback) { - for (const auto& entity : m_data) callback(entity); -} - -} // namespace format::input +} // namespace di::data_format diff --git a/src/data_format/typed_symbol_list.h b/src/data_format/typed_symbol_list.h new file mode 100644 index 0000000..dba24ae --- /dev/null +++ b/src/data_format/typed_symbol_list.h @@ -0,0 +1,23 @@ +#pragma once + +#include "data_format/type/typed_symbol.h" + +namespace di::data_format { + +class TypedSymbolList { +public: + using for_each_callback_t = std::function; + + explicit TypedSymbolList(const std::string& path) + : TypedSymbolList(std::vector{path}) {}; + explicit TypedSymbolList(const std::vector& paths); + + constexpr void for_each(const for_each_callback_t& callback) const { + for (const auto& entity : m_data) callback(entity); + } + +private: + std::unordered_set m_data; +}; + +} // namespace di::data_format diff --git a/src/frontend_action/dump_symbol.cpp b/src/frontend_action/dump_symbol.cpp new file mode 100644 index 0000000..cf6e8fe --- /dev/null +++ b/src/frontend_action/dump_symbol.cpp @@ -0,0 +1,119 @@ +#include "frontend_action/dump_symbol.h" + +#include +#include +#include +#include + +using namespace clang; + +namespace { + +bool config_record_decl_name = false; + +class Container : private std::unordered_set { +public: + void put(const std::string& symbol) { emplace(symbol); } + + void write_to(const std::string& path) { + std::ofstream ofs(path); + if (ofs) { + for (const auto& E : *this) { + ofs << E << "\n"; + } + } + } +}; + +class Visitor : public RecursiveASTVisitor { +public: + Visitor(ASTContext& context, Container& container) + : m_namegen(context), + m_symbol_container(container) {} + + bool VisitNamedDecl(NamedDecl* decl) { + if (!decl || !decl->getDeclName()) return true; + + // FIXME: There are likely other contexts in which it makes + // no sense to ask for a mangled name. + if (isa(decl->getDeclContext())) return true; + + // If the declaration is dependent or is in a dependent + // context, then the mangling is unlikely to be meaningful + // (and in some cases may cause "don't know how to mangle + // this" assertion failures. + if (decl->isTemplated()) return true; + + // Mangled names are not meaningful for locals, and may not + // be well-defined in the case of VLAs. + auto* var_decl = dyn_cast(decl); + if (var_decl && var_decl->hasLocalStorage()) return true; + + // Do not mangle template deduction guides. + if (isa(decl)) return true; + + std::string mangled_name = m_namegen.getName(decl); + if (!mangled_name.empty()) { + if (config_record_decl_name) { + mangled_name = std::format( + "{}, {}", + decl->getDeclKindName(), + mangled_name + ); + } + m_symbol_container.put(mangled_name); + } + + return true; + } + +private: + ASTNameGenerator m_namegen; + Container& m_symbol_container; +}; + +class Consumer : public ASTConsumer { +public: + explicit Consumer(ASTContext& Context) {} + + void HandleTranslationUnit(ASTContext& Context) override { + Container Symbols; + + Visitor(Context, Symbols) + .TraverseDecl(Context.getTranslationUnitDecl()); + + // Save + auto& SM = Context.getSourceManager(); + auto Loc = SM.getLocForStartOfFile(SM.getMainFileID()); + Symbols.write_to(SM.getFilename(Loc).str() + ".symbols"); + } +}; + +} // namespace + +namespace di::frontend_action { + +std::unique_ptr DumpSymbolFrontendAction::CreateASTConsumer( + CompilerInstance& instance, + llvm::StringRef +) { + return std::make_unique(instance.getASTContext()); +} + +bool DumpSymbolFrontendAction::ParseArgs( + const CompilerInstance&, + const std::vector& args +) { + for (const auto& arg : args) { + if (arg.ends_with("record-decl-name")) { + config_record_decl_name = true; + } + } + return true; +} + +PluginASTAction::ActionType DumpSymbolFrontendAction::getActionType() { + return AddAfterMainAction; +} + +} // namespace di::frontend_action diff --git a/src/frontend_action/dump_symbol.h b/src/frontend_action/dump_symbol.h new file mode 100644 index 0000000..b4feefa --- /dev/null +++ b/src/frontend_action/dump_symbol.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace clang { +class ASTConsumer; +class CompilerInstance; +} // namespace clang + +namespace di::frontend_action { + +class DumpSymbolFrontendAction : public clang::PluginASTAction { +protected: + std::unique_ptr CreateASTConsumer( + clang::CompilerInstance& instance, + llvm::StringRef + ) override; + + bool ParseArgs( + const clang::CompilerInstance&, + const std::vector& args + ) override; + + ActionType getActionType() override; +}; + +} // namespace di::frontend_action diff --git a/AskRVA/src/nonstd.h b/src/nonstd.h similarity index 80% rename from AskRVA/src/nonstd.h rename to src/nonstd.h index d1287e0..10f19b2 100644 --- a/AskRVA/src/nonstd.h +++ b/src/nonstd.h @@ -1,5 +1,10 @@ #pragma once +template +constexpr auto static_unique_ptr_cast(std::unique_ptr&& F) { + return std::unique_ptr(static_cast(F.release())); +} + // From: // https://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set @@ -29,7 +34,9 @@ struct HashValueImpl { template struct HashValueImpl { - static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } + static void apply(size_t& seed, Tuple const& tuple) { + hash_combine(seed, std::get<0>(tuple)); + } }; } // namespace diff --git a/MakePDB/src/binary/COFF.cpp b/src/object_file/COFF.cpp similarity index 95% rename from MakePDB/src/binary/COFF.cpp rename to src/object_file/COFF.cpp index e33c65c..309edee 100644 --- a/MakePDB/src/binary/COFF.cpp +++ b/src/object_file/COFF.cpp @@ -1,6 +1,6 @@ -#include "binary/COFF.h" +#include "object_file/COFF.h" -namespace makepdb::binary { +namespace di::object_file { COFF::COFF(std::string_view path) { using namespace object; @@ -67,4 +67,4 @@ object::COFFObjectFile const& COFF::get_owning_coff() const { return *m_owning_binary.getBinary(); } -} // namespace makepdb::binary +} // namespace di::object_file diff --git a/MakePDB/src/binary/COFF.h b/src/object_file/COFF.h similarity index 88% rename from MakePDB/src/binary/COFF.h rename to src/object_file/COFF.h index b1eeaca..f5fbc44 100644 --- a/MakePDB/src/binary/COFF.h +++ b/src/object_file/COFF.h @@ -2,7 +2,7 @@ #include -namespace makepdb::binary { +namespace di::object_file { class COFF { public: @@ -20,4 +20,4 @@ private: object::OwningBinary m_owning_binary; }; -} // namespace makepdb::binary +} // namespace di::object_file diff --git a/MakePDB/src/binary/PDB.cpp b/src/object_file/PDB.cpp similarity index 79% rename from MakePDB/src/binary/PDB.cpp rename to src/object_file/PDB.cpp index 97b88cc..c4b3e9e 100644 --- a/MakePDB/src/binary/PDB.cpp +++ b/src/object_file/PDB.cpp @@ -1,15 +1,15 @@ -#include "binary/PDB.h" +#include "object_file/PDB.h" -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" +#include +#include +#include +#include #include +#include using namespace llvm::pdb; -namespace makepdb::binary { +namespace di::object_file { PDB::PDB() : m_builder(m_allocator) { constexpr uint32_t block_size = 4096; @@ -90,12 +90,12 @@ void PDB::build_TPI() { IPI.setVersionHeader(PdbRaw_TpiVer::PdbTpiV80); if (m_owning_raw_type_data) { - m_owning_raw_type_data->for_each( + m_owning_raw_type_data->for_each( [&TPI](codeview::TypeIndex index, const codeview::CVType& type) { TPI.addTypeRecord(type.RecordData, std::nullopt); } ); - m_owning_raw_type_data->for_each( + m_owning_raw_type_data->for_each( [&IPI](codeview::TypeIndex index, const codeview::CVType& type) { IPI.addTypeRecord(type.RecordData, std::nullopt); } @@ -105,24 +105,23 @@ void PDB::build_TPI() { void PDB::build_GSI() { std::vector publics; - m_owning_symbol_data->for_each([&publics, - this](const SymbolDataEntity& entity) { + m_owning_symbol_data->for_each([&publics, this](const BoundSymbol& entity) { BulkPublic symbol; auto section_index = - m_owning_coff->get_section_index(entity.rva - m_image_base); + m_owning_coff->get_section_index(entity.m_rva - m_image_base); auto section_or_err = m_owning_coff->get_owning_coff().getSection(section_index + 1); if (!section_or_err) { throw std::runtime_error("Invalid section."); } - symbol.Name = strdup(entity.symbol_name.c_str()); - symbol.NameLen = entity.symbol_name.size(); + symbol.Name = strdup(entity.m_symbol_name.c_str()); + symbol.NameLen = entity.m_symbol_name.size(); symbol.Segment = section_index + 1; symbol.Offset = - entity.rva - m_image_base - section_or_err.get()->VirtualAddress; - if (entity.is_function) + entity.m_rva - m_image_base - section_or_err.get()->VirtualAddress; + if (entity.m_is_function) symbol.setFlags(codeview::PublicSymFlags::Function); publics.emplace_back(symbol); @@ -131,4 +130,4 @@ void PDB::build_GSI() { m_builder.getGsiBuilder().addPublicSymbols(std::move(publics)); } -} // namespace makepdb::binary +} // namespace di::object_file diff --git a/src/object_file/PDB.h b/src/object_file/PDB.h new file mode 100644 index 0000000..c2cc5ba --- /dev/null +++ b/src/object_file/PDB.h @@ -0,0 +1,53 @@ +#pragma once + +#include "object_file/COFF.h" + +#include "data_format/bound_symbol_list.h" +#include "data_format/raw_type_data.h" + +#include +#include + +namespace di::object_file { + +class PDB { +public: + using owning_coff_t = std::unique_ptr; + using owning_symbol_data_t = std::unique_ptr; + using owning_type_data_t = std::unique_ptr; + + explicit PDB(); + + void set_coff_object(owning_coff_t coff_object) { + m_owning_coff = std::move(coff_object); + m_image_base = m_owning_coff->get_owning_coff().getImageBase(); + } + + void set_symbol_data(owning_symbol_data_t symbol_data) { + m_owning_symbol_data = std::move(symbol_data); + } + void set_raw_type_data(owning_type_data_t raw_type_data) { + m_owning_raw_type_data = std::move(raw_type_data); + } + + void write(std::string_view path); + +private: + void build(); + + inline void build_Info(); + inline void build_DBI(); + inline void build_TPI(); + inline void build_GSI(); + + owning_coff_t m_owning_coff; + owning_symbol_data_t m_owning_symbol_data; + owning_type_data_t m_owning_raw_type_data; + + uint64_t m_image_base; + + BumpPtrAllocator m_allocator; + pdb::PDBFileBuilder m_builder; +}; + +} // namespace di::object_file diff --git a/AskRVA/src/pch.h b/src/pch.h similarity index 70% rename from AskRVA/src/pch.h rename to src/pch.h index 469dbf1..bc4a97f 100644 --- a/AskRVA/src/pch.h +++ b/src/pch.h @@ -1,13 +1,18 @@ +// Work on llvm namespace. + +namespace llvm {} +using namespace llvm; + // Standard Libraries -#include -#include - - #include #include +#include +#include +#include + #include #include @@ -16,5 +21,8 @@ #include +#include + // Helper + #include "nonstd.h" diff --git a/AskRVA/src/main.cpp b/src/tools/askrva/main.cpp similarity index 61% rename from AskRVA/src/main.cpp rename to src/tools/askrva/main.cpp index 85d7e1c..8ef1265 100644 --- a/AskRVA/src/main.cpp +++ b/src/tools/askrva/main.cpp @@ -1,22 +1,26 @@ -#include "format/input/all.h" -#include "format/output/all.h" - #include "util/string.h" +#include "data_format/bound_symbol_list.h" +#include "data_format/human_readable_symbol_list.h" +#include "data_format/raw_text.h" +#include "data_format/typed_symbol_list.h" + #include +#if DI_USE_NATIVE_SYMBOL_RESOLVER #include +#endif -using namespace format; +enum class OutputFormat { Text, MakePDB }; -constexpr auto VERSION = "1.0.0"; +using namespace di; [[nodiscard]] auto load_args(int argc, char* argv[]) { - argparse::ArgumentParser program("askrva", VERSION); + argparse::ArgumentParser program("askrva"); struct { OutputFormat m_output_format; - std::vector m_input_path; + std::vector m_input_paths; std::string m_output_path; std::optional m_output_failed_path; @@ -28,7 +32,7 @@ constexpr auto VERSION = "1.0.0"; program.add_argument("path") .help("Path to the symbol list file.") - .store_into(args.m_input_path) + .store_into(args.m_input_paths) .nargs(argparse::nargs_pattern::at_least_one) .required(); @@ -42,7 +46,7 @@ constexpr auto VERSION = "1.0.0"; program.add_argument("--output-format") .help("Specify output format.") - .choices("auto", "text", "fakepdb", "makepdb") + .choices("auto", "text", "makepdb") .default_value("auto") .store_into(output_format); @@ -56,8 +60,6 @@ constexpr auto VERSION = "1.0.0"; switch (H(output_format)) { case H("text"): return OutputFormat::Text; - case H("fakepdb"): - return OutputFormat::FakePDB; case H("makepdb"): return OutputFormat::MakePDB; case H("auto"): @@ -81,23 +83,36 @@ constexpr auto VERSION = "1.0.0"; int main(int argc, char* argv[]) try { auto args = load_args(argc, argv); - auto symlist = input::SymbolListFile::load(args.m_input_path); + auto symlist = data_format::TypedSymbolList(args.m_input_paths); - auto output_file = output::create(args.m_output_format); + data_format::BoundSymbolList bound_symbol_list; + data_format::HumanReadableSymbolList human_readable_symbol_list; + data_format::RawText raw_text; - symlist.for_each([&output_file](const input::Symbol& symbol) { + symlist.for_each([&](const TypedSymbol& symbol) { auto& sym = symbol.m_name; - auto rva = pl::symbol_provider::pl_resolve_symbol_silent_n(sym.c_str(), sym.size()); +#if DI_USE_NATIVE_SYMBOL_RESOLVER + auto rva = pl::symbol_provider::pl_resolve_symbol_silent_n( + sym.c_str(), + sym.size() + ); +#else + auto rva = (void*)nullptr; // TODO +#endif if (rva) { - output_file->record(symbol.m_name, reinterpret_cast(rva), symbol.m_type.isFunction()); + bound_symbol_list.record( + symbol.m_name, + reinterpret_cast(rva), + symbol.m_type.is_function() + ); } else { - output_file->record_failure(symbol.m_name); + raw_text.record(symbol.m_name); } }); - output_file->save(args.m_output_path); + bound_symbol_list.write_to(args.m_output_path); if (args.m_output_failed_path) { - output_file->save_failure(*args.m_output_failed_path); + raw_text.write_to(*args.m_output_failed_path); } std::println("Everything is OK."); diff --git a/BlobExtractor/src/main.cpp b/src/tools/blob-extractor/main.cpp similarity index 96% rename from BlobExtractor/src/main.cpp rename to src/tools/blob-extractor/main.cpp index d69192f..7e764cd 100644 --- a/BlobExtractor/src/main.cpp +++ b/src/tools/blob-extractor/main.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include -#include #define XXH_INLINE_ALL #include "xxhash.h" diff --git a/src/tools/dumpsym/plugin.cpp b/src/tools/dumpsym/plugin.cpp new file mode 100644 index 0000000..80b8304 --- /dev/null +++ b/src/tools/dumpsym/plugin.cpp @@ -0,0 +1,9 @@ +#include "frontend_action/dump_symbol.h" + +#include + +using namespace clang; + +static FrontendPluginRegistry::Add< + di::frontend_action::DumpSymbolFrontendAction> + X("dumpsym", "Extract all declared symbols from a TU."); diff --git a/ExtractSYM/src/main.cpp b/src/tools/extractsym/main.cpp similarity index 98% rename from ExtractSYM/src/main.cpp rename to src/tools/extractsym/main.cpp index 0a7564a..884f9ef 100644 --- a/ExtractSYM/src/main.cpp +++ b/src/tools/extractsym/main.cpp @@ -9,9 +9,6 @@ #include -#include -#include - using namespace llvm; using namespace llvm::pdb; using namespace llvm::codeview; diff --git a/MakePDB/src/main.cpp b/src/tools/makepdb/main.cpp similarity index 72% rename from MakePDB/src/main.cpp rename to src/tools/makepdb/main.cpp index 2b01da0..5b79c40 100644 --- a/MakePDB/src/main.cpp +++ b/src/tools/makepdb/main.cpp @@ -1,16 +1,16 @@ #include -#include "binary/COFF.h" -#include "binary/PDB.h" +#include "object_file/COFF.h" +#include "object_file/PDB.h" -#include "raw_type_data.h" -#include "symbol_data.h" +#include "data_format/bound_symbol_list.h" +#include "data_format/raw_type_data.h" -using namespace makepdb; +using namespace di; [[nodiscard]] auto load_args(int argc, char* argv[]) { - argparse::ArgumentParser program("makepdb", "1.1.0"); + argparse::ArgumentParser program("makepdb"); struct { std::string server_program_path; @@ -53,16 +53,18 @@ int main(int argc, char* argv[]) try { auto args = load_args(argc, argv); auto server_program = - std::make_unique(args.server_program_path); + std::make_unique(args.server_program_path); - auto symbol_data = std::make_unique(args.symbol_data_path); + auto symbol_data = + std::make_unique(args.symbol_data_path); - std::unique_ptr raw_type_data; + std::unique_ptr raw_type_data; if (args.typeinfo_pdb_path) { - raw_type_data = std::make_unique(*args.typeinfo_pdb_path); + raw_type_data = + std::make_unique(*args.typeinfo_pdb_path); } - binary::PDB pdb; + object_file::PDB pdb; pdb.set_coff_object(std::move(server_program)); pdb.set_symbol_data(std::move(symbol_data)); pdb.set_raw_type_data(std::move(raw_type_data)); diff --git a/AskRVA/src/util/string.h b/src/util/string.h similarity index 74% rename from AskRVA/src/util/string.h rename to src/util/string.h index e563324..7dc2892 100644 --- a/AskRVA/src/util/string.h +++ b/src/util/string.h @@ -1,10 +1,10 @@ #pragma once -namespace util::string { +namespace di::util::string { constexpr unsigned int H(std::string_view str, unsigned int hash = 0) { for (char c : str) hash = hash * 31 + static_cast(c); return hash; } -} // namespace util::string +} // namespace di::util::string diff --git a/xmake.lua b/xmake.lua new file mode 100644 index 0000000..b7daafd --- /dev/null +++ b/xmake.lua @@ -0,0 +1,120 @@ +add_rules('mode.debug', 'mode.release') + +add_requires('argparse 3.1') +add_requires('nlohmann_json 3.11.3') +add_requires('xxhash 0.8.3') +add_requires('boost 1.87.0') + +add_requires('llvm') + +--- options + +option('symbol-resolver') + set_default('builtin') + set_showmenu(true) + set_description('Select a symbol resolver.') + set_values('builtin', 'native') + before_check(function (option) + -- the native symbol resolution backend is only available under windows, because liteldev + -- has not released a linux version. + if option:value() == 'native' and not is_plat('windows') then + raise('the native symbol resolver does not support this platform.') + end + end) +option_end() + +if is_config('symbol-resolver', 'native') then + add_repositories('liteldev-repo https://github.com/LiteLDev/xmake-repo.git') + add_requires('preloader 1.12.0') +end + +--- global settings + +set_languages('c23', 'c++23') +set_warnings('all') + +add_includedirs('src') + +set_policy("build.optimization.lto", true) + +if is_mode('debug') then + add_defines('DI_DEBUG') +end + +--- targets + +target('libdi') + set_kind('static') + add_files('src/**.cpp') + set_pcxxheader('src/pch.h') + + set_basename('di') + + add_packages( + 'nlohmann_json' + ) + + remove_files('src/tools/**') + +target('askrva') + set_kind('binary') + add_deps('libdi') + add_files('src/tools/askrva/**.cpp') + set_pcxxheader('src/pch.h') + + add_packages( + 'argparse', + 'nlohmann_json' + ) + + if is_config('symbol-resolver', 'native') then + add_packages('preloader') + add_defines('DI_USE_NATIVE_SYMBOL_RESOLVER=1') + end + +target('blob-extractor') + set_kind('binary') + add_deps('libdi') + add_files('src/tools/blob-extractor/**.cpp') + set_pcxxheader('src/pch.h') + +target('dumpsym') + set_kind('shared') + add_deps('libdi') + add_files('src/tools/dumpsym/**.cpp') + set_pcxxheader('src/pch.h') + + add_packages( + 'llvm' + ) + +target('extractsym') + set_kind('binary') + add_deps('libdi') + add_files('src/tools/extractsym/**.cpp') + set_pcxxheader('src/pch.h') + + add_packages( + 'llvm', + 'argparse' + ) + + if is_plat('linux') then -- workaround to fix link problem. + add_links('LLVM') + end + +target('makepdb') + set_kind('binary') + add_deps('libdi') + add_files('src/tools/makepdb/**.cpp') + set_pcxxheader('src/pch.h') + + add_packages( + 'llvm', + 'nlohmann_json', + 'argparse' + ) + + if is_plat('linux') then + add_links('LLVM') + end