From b00525a10746de26040d201fa2ca7fb075d1f83b Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 12 Jun 2026 23:49:48 +0200 Subject: utils/ -> src/utils/ --- CMakeLists.txt | 1 - src/CMakeLists.txt | 4 +- src/utils/CMakeLists.txt | 27 ++++++++++ src/utils/addr2name.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++ src/utils/command_line.hpp | 73 +++++++++++++++++++++++++++ src/utils/enum_symbols.cpp | 99 +++++++++++++++++++++++++++++++++++++ src/utils/name2addr.cpp | 86 ++++++++++++++++++++++++++++++++ src/utils/pdb_descr.hpp | 61 +++++++++++++++++++++++ utils/CMakeLists.txt | 27 ---------- utils/addr2name.cpp | 119 --------------------------------------------- utils/command_line.hpp | 73 --------------------------- utils/enum_symbols.cpp | 99 ------------------------------------- utils/name2addr.cpp | 86 -------------------------------- utils/pdb_descr.hpp | 61 ----------------------- 14 files changed, 468 insertions(+), 467 deletions(-) create mode 100644 src/utils/CMakeLists.txt create mode 100644 src/utils/addr2name.cpp create mode 100644 src/utils/command_line.hpp create mode 100644 src/utils/enum_symbols.cpp create mode 100644 src/utils/name2addr.cpp create mode 100644 src/utils/pdb_descr.hpp delete mode 100644 utils/CMakeLists.txt delete mode 100644 utils/addr2name.cpp delete mode 100644 utils/command_line.hpp delete mode 100644 utils/enum_symbols.cpp delete mode 100644 utils/name2addr.cpp delete mode 100644 utils/pdb_descr.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0897012..09cdb18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,5 @@ add_subdirectory(3rdparty/winapi/common EXCLUDE_FROM_ALL) add_subdirectory(src) add_subdirectory(test) -add_subdirectory(utils) install(FILES LICENSE.txt DESTINATION share) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e33a267..a78f35a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ find_package(Boost CONFIG REQUIRED) file(GLOB_RECURSE winapi_debug_include CONFIGURE_DEPENDS "../include/*.hpp") -file(GLOB_RECURSE winapi_debug_src CONFIGURE_DEPENDS "*.cpp") +file(GLOB winapi_debug_src CONFIGURE_DEPENDS "*.cpp") add_library(winapi_debug ${winapi_debug_include} ${winapi_debug_src}) target_compile_definitions(winapi_debug PUBLIC _NO_CVCONST_H) target_include_directories(winapi_debug PUBLIC ../include/) @@ -19,3 +19,5 @@ if(MSVC_VERSION EQUAL 1900) # DbgHelp warnings on Visual Studio 2015: target_compile_options(winapi_debug PUBLIC /wd4091) endif() + +add_subdirectory(utils) diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt new file mode 100644 index 0000000..51ab17d --- /dev/null +++ b/src/utils/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package(Boost CONFIG REQUIRED COMPONENTS program_options) + +function(add_util name src) + add_executable("${name}" ${src}) + target_link_libraries("${name}" PRIVATE winapi_debug) + target_link_libraries("${name}" PRIVATE Boost::disable_autolinking Boost::program_options) + install(TARGETS "${name}" RUNTIME DESTINATION bin) + if(MSVC) + install(FILES "$" DESTINATION bin OPTIONAL) + endif() +endfunction() + +add_util(enum_symbols enum_symbols.cpp command_line.hpp pdb_descr.hpp) +add_util(name2addr name2addr.cpp) +add_util(addr2name addr2name.cpp command_line.hpp pdb_descr.hpp) + +if(MSVC) + find_package(Python3 REQUIRED COMPONENTS Interpreter) + add_test(NAME enum_symbols COMMAND Python3::Interpreter + "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/tools/ctest-driver.py" + run + --pass-regex test_ns::baz test_ns::bar test_ns::foo test_ns::var + -- + "$" + --pdb "$" + --mask "test_ns:*") +endif() diff --git a/src/utils/addr2name.cpp b/src/utils/addr2name.cpp new file mode 100644 index 0000000..98b53b9 --- /dev/null +++ b/src/utils/addr2name.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "winapi-debug" project. +// For details, see https://github.com/egor-tensin/winapi-debug. +// Distributed under the MIT License. + +#include "command_line.hpp" +#include "pdb_descr.hpp" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace { + +class Addr2Name : public SettingsParser { +public: + explicit Addr2Name(int argc, char** argv) : SettingsParser{argc, argv} { + namespace po = boost::program_options; + + visible.add_options()( + "pdb", po::value>(&pdbs)->value_name("ADDR,PATH"), "load a PDB file"); + visible.add_options()( + "lines,l", po::bool_switch(&lines), "try to resolve source files & line numbers"); + hidden.add_options()( + "address", + po::value>(&addresses)->value_name("ADDR"), + "add an address to resolve"); + positional.add("address", -1); + } + + const char* get_short_description() const override { + return "[-h|--help] [--pdb ADDR,PATH]... [-l|--lines] [--] [ADDR]..."; + } + + std::vector pdbs; + std::vector addresses; + bool lines = false; +}; + +std::string format_symbol(const winapi::Module& module, const winapi::Symbol& symbol) { + const auto symbol_str = std::format("{}!{}", module.get_name(), symbol.get_name()); + const auto displacement = symbol.get_displacement(); + if (!displacement) + return symbol_str; + return std::format("{}+{}", symbol_str, winapi::address::format(displacement)); +} + +std::string format_line_info(const winapi::LineInfo& line_info) { + return std::format("[{} @ {}]", line_info.file_path, line_info.line_number); +} + +void dump_error(const std::exception& e) { + std::cerr << std::format("error: {}\n", e.what()); +} + +void resolve_symbol(const winapi::PostMortem& analysis, + winapi::Address address, + bool lines = false) { + try { + const auto symbol = analysis.resolve_symbol(address); + const auto& module = analysis.module_with_offline_base(symbol.get_offline_base()); + + std::ostringstream msg; + msg << format_symbol(module, symbol); + + if (lines) { + try { + const auto line_info = analysis.resolve_line(address); + msg << ' ' << format_line_info(line_info); + } catch (const std::exception& e) { + dump_error(e); + } + } + + std::cout << msg.str() << '\n'; + } catch (const std::exception& e) { + dump_error(e); + std::cout << winapi::address::format(address) << '\n'; + } +} + +} // namespace + +int main(int argc, char* argv[]) { + try { + Addr2Name settings{argc, argv}; + + try { + settings.parse(argc, argv); + } catch (const boost::program_options::error& e) { + settings.usage_error(e); + return 1; + } + + if (settings.exit_with_usage) { + settings.usage(); + return 0; + } + + winapi::PostMortem analysis; + + for (const auto& pdb : settings.pdbs) + analysis.add_pdb(pdb.online_base, pdb.path); + + for (const auto& address : settings.addresses) + resolve_symbol(analysis, address, settings.lines); + } catch (const std::exception& e) { + dump_error(e); + return 1; + } + return 0; +} diff --git a/src/utils/command_line.hpp b/src/utils/command_line.hpp new file mode 100644 index 0000000..d3178f1 --- /dev/null +++ b/src/utils/command_line.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "winapi-debug" project. +// For details, see https://github.com/egor-tensin/winapi-debug. +// Distributed under the MIT License. + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +class SettingsParser { +public: + explicit SettingsParser(int, char** argv) : prog_name{extract_filename(argv[0])} { + visible.add_options()("help,h", "show this message and exit"); + } + + virtual ~SettingsParser() = default; + + virtual const char* get_short_description() const { + return "[--option VALUE]..."; + } + + virtual void parse(int argc, char* argv[]) { + boost::program_options::options_description all; + all.add(hidden).add(visible); + boost::program_options::variables_map vm; + boost::program_options::store(boost::program_options::command_line_parser{argc, argv} + .options(all) + .positional(positional) + .run(), + vm); + if (vm.count("help")) + exit_with_usage = true; + else + boost::program_options::notify(vm); + } + + bool exit_with_usage = false; + + void usage() const { + std::cout << *this; + } + + void usage_error(const std::exception& e) const { + std::cerr << std::format("usage error: {}\n", e.what()); + std::cerr << *this; + } + +protected: + boost::program_options::options_description hidden; + boost::program_options::options_description visible; + boost::program_options::positional_options_description positional; + +private: + static std::string extract_filename(char* path) { + return std::filesystem::path{path}.filename().string(); + } + + const std::string prog_name; + + friend std::ostream& operator<<(std::ostream& os, const SettingsParser& parser) { + const auto short_descr = parser.get_short_description(); + os << std::format("usage: {} {}\n", parser.prog_name, short_descr); + os << parser.visible; + return os; + } +}; diff --git a/src/utils/enum_symbols.cpp b/src/utils/enum_symbols.cpp new file mode 100644 index 0000000..645bc13 --- /dev/null +++ b/src/utils/enum_symbols.cpp @@ -0,0 +1,99 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "winapi-debug" project. +// For details, see https://github.com/egor-tensin/winapi-debug. +// Distributed under the MIT License. + +#include "command_line.hpp" + +#include + +#include + +#include +#include +#include +#include + +namespace { + +class EnumSymbols : public SettingsParser { +public: + explicit EnumSymbols(int argc, char** argv) : SettingsParser{argc, argv} { + namespace po = boost::program_options; + + visible.add_options()("pdb", + po::value>(&pdbs)->value_name("PATH"), + "load a PDB file"); + visible.add_options()( + "functions", + po::value(&tag)->implicit_value(function_tag)->zero_tokens(), + "only list functions"); + visible.add_options()( + "mask", po::value(&symbol_mask)->value_name("MASK"), "symbol mask"); + } + + const char* get_short_description() const override { + return "[-h|--help] [--pdb PATH]... [--functions] [--mask MASK]"; + } + + std::vector pdbs; + + bool type_specified() const { + return tag != reserved_tag; + } + + winapi::Symbol::Type get_type() const { + return static_cast(tag); + } + + std::string get_mask() const { + return symbol_mask; + } + +private: + static constexpr auto reserved_tag = + static_cast(winapi::Symbol::Type::RESERVED); + static constexpr auto function_tag = + static_cast(winapi::Symbol::Type::Function); + + winapi::symbol::Tag tag = reserved_tag; + std::string symbol_mask{winapi::DbgHelp::all_symbols}; +}; + +constexpr winapi::symbol::Tag EnumSymbols::reserved_tag; +constexpr winapi::symbol::Tag EnumSymbols::function_tag; + +} // namespace + +int main(int argc, char* argv[]) { + try { + EnumSymbols settings{argc, argv}; + + try { + settings.parse(argc, argv); + } catch (const boost::program_options::error& e) { + settings.usage_error(e); + return 1; + } + + if (settings.exit_with_usage) { + settings.usage(); + return 0; + } + + const auto dbghelp = winapi::DbgHelp::post_mortem(); + + for (const auto& pdb : settings.pdbs) { + const auto id = dbghelp.load_pdb(pdb); + + dbghelp.enum_symbols(id, settings.get_mask(), [&](const winapi::SymbolInfo& symbol) { + if (!settings.type_specified() || settings.get_type() == symbol.get_type()) + std::cout << symbol.get_name() << '\n'; + }); + } + } catch (const std::exception& e) { + std::cerr << std::format("error: {}\n", e.what()); + return 1; + } + return 0; +} diff --git a/src/utils/name2addr.cpp b/src/utils/name2addr.cpp new file mode 100644 index 0000000..d253aa9 --- /dev/null +++ b/src/utils/name2addr.cpp @@ -0,0 +1,86 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "winapi-debug" project. +// For details, see https://github.com/egor-tensin/winapi-debug. +// Distributed under the MIT License. + +#include "command_line.hpp" +#include "pdb_descr.hpp" + +#include + +#include + +#include +#include +#include +#include +#include + +namespace { + +class Name2Addr : public SettingsParser { +public: + explicit Name2Addr(int argc, char** argv) : SettingsParser{argc, argv} { + namespace po = boost::program_options; + + visible.add_options()( + "pdb", po::value>(&pdbs)->value_name("ADDR,PATH"), "load a PDB file"); + hidden.add_options()("name", + po::value>(&names)->value_name("NAME"), + "add a name to resolve"); + positional.add("name", -1); + } + + const char* get_short_description() const override { + return "[-h|--help] [--pdb ADDR,PATH]... [--] [NAME]..."; + } + + std::vector pdbs; + std::vector names; +}; + +void dump_error(const std::exception& e) { + std::cerr << std::format("error: {}\n", e.what()); +} + +void resolve_symbol(const winapi::PostMortem& analysis, std::string_view name) { + try { + const auto address = analysis.resolve_symbol(name).get_online_address(); + std::cout << winapi::address::format(address) << '\n'; + } catch (const std::exception& e) { + dump_error(e); + std::cout << name << '\n'; + } +} + +} // namespace + +int main(int argc, char* argv[]) { + try { + Name2Addr settings{argc, argv}; + + try { + settings.parse(argc, argv); + } catch (const boost::program_options::error& e) { + settings.usage_error(e); + return 1; + } + + if (settings.exit_with_usage) { + settings.usage(); + return 0; + } + + winapi::PostMortem analysis; + + for (const auto& pdb : settings.pdbs) + analysis.add_pdb(pdb.online_base, pdb.path); + + for (const auto& name : settings.names) + resolve_symbol(analysis, name); + } catch (const std::exception& e) { + dump_error(e); + return 1; + } + return 0; +} diff --git a/src/utils/pdb_descr.hpp b/src/utils/pdb_descr.hpp new file mode 100644 index 0000000..c2e720a --- /dev/null +++ b/src/utils/pdb_descr.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "winapi-debug" project. +// For details, see https://github.com/egor-tensin/winapi-debug. +// Distributed under the MIT License. + +#pragma once + +#include + +#include + +#include +#include + +struct PDB { + winapi::Address online_base; + std::string path; + + static PDB parse(const std::string& src) { + static constexpr auto sep = ','; + + const auto sep_pos = src.find(sep); + if (sep_pos == std::string::npos) + throw boost::program_options::invalid_option_value{src}; + + winapi::Address online_base; + if (!winapi::address::parse(online_base, src.substr(0, sep_pos))) + throw boost::program_options::invalid_option_value{src}; + + return {online_base, src.substr(sep_pos + 1)}; + } + + static winapi::Address parse_address(const std::string& src) { + winapi::Address dest; + if (!winapi::address::parse(dest, src)) + throw boost::program_options::invalid_option_value{src}; + return dest; + } +}; + +template +void validate(boost::any& dest, + const std::vector>& src_tokens, + PDB*, + int) { + namespace po = boost::program_options; + po::validators::check_first_occurrence(dest); + const auto& src_token = po::validators::get_single_string(src_tokens); + dest = boost::any{PDB::parse(src_token)}; +} + +template +void validate(boost::any& dest, + const std::vector>& src_tokens, + winapi::Address*, + int) { + namespace po = boost::program_options; + po::validators::check_first_occurrence(dest); + const auto& src_token = po::validators::get_single_string(src_tokens); + dest = boost::any{PDB::parse_address(src_token)}; +} diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt deleted file mode 100644 index ce0ec07..0000000 --- a/utils/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -find_package(Boost CONFIG REQUIRED COMPONENTS program_options) - -function(add_util name src) - add_executable("${name}" ${src}) - target_link_libraries("${name}" PRIVATE winapi_debug) - target_link_libraries("${name}" PRIVATE Boost::disable_autolinking Boost::program_options) - install(TARGETS "${name}" RUNTIME DESTINATION bin) - if(MSVC) - install(FILES "$" DESTINATION bin OPTIONAL) - endif() -endfunction() - -add_util(enum_symbols enum_symbols.cpp command_line.hpp pdb_descr.hpp) -add_util(name2addr name2addr.cpp) -add_util(addr2name addr2name.cpp command_line.hpp pdb_descr.hpp) - -if(MSVC) - find_package(Python3 REQUIRED COMPONENTS Interpreter) - add_test(NAME enum_symbols COMMAND Python3::Interpreter - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/tools/ctest-driver.py" - run - --pass-regex test_ns::baz test_ns::bar test_ns::foo test_ns::var - -- - "$" - --pdb "$" - --mask "test_ns:*") -endif() diff --git a/utils/addr2name.cpp b/utils/addr2name.cpp deleted file mode 100644 index 98b53b9..0000000 --- a/utils/addr2name.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "winapi-debug" project. -// For details, see https://github.com/egor-tensin/winapi-debug. -// Distributed under the MIT License. - -#include "command_line.hpp" -#include "pdb_descr.hpp" - -#include - -#include - -#include -#include -#include -#include -#include -#include - -namespace { - -class Addr2Name : public SettingsParser { -public: - explicit Addr2Name(int argc, char** argv) : SettingsParser{argc, argv} { - namespace po = boost::program_options; - - visible.add_options()( - "pdb", po::value>(&pdbs)->value_name("ADDR,PATH"), "load a PDB file"); - visible.add_options()( - "lines,l", po::bool_switch(&lines), "try to resolve source files & line numbers"); - hidden.add_options()( - "address", - po::value>(&addresses)->value_name("ADDR"), - "add an address to resolve"); - positional.add("address", -1); - } - - const char* get_short_description() const override { - return "[-h|--help] [--pdb ADDR,PATH]... [-l|--lines] [--] [ADDR]..."; - } - - std::vector pdbs; - std::vector addresses; - bool lines = false; -}; - -std::string format_symbol(const winapi::Module& module, const winapi::Symbol& symbol) { - const auto symbol_str = std::format("{}!{}", module.get_name(), symbol.get_name()); - const auto displacement = symbol.get_displacement(); - if (!displacement) - return symbol_str; - return std::format("{}+{}", symbol_str, winapi::address::format(displacement)); -} - -std::string format_line_info(const winapi::LineInfo& line_info) { - return std::format("[{} @ {}]", line_info.file_path, line_info.line_number); -} - -void dump_error(const std::exception& e) { - std::cerr << std::format("error: {}\n", e.what()); -} - -void resolve_symbol(const winapi::PostMortem& analysis, - winapi::Address address, - bool lines = false) { - try { - const auto symbol = analysis.resolve_symbol(address); - const auto& module = analysis.module_with_offline_base(symbol.get_offline_base()); - - std::ostringstream msg; - msg << format_symbol(module, symbol); - - if (lines) { - try { - const auto line_info = analysis.resolve_line(address); - msg << ' ' << format_line_info(line_info); - } catch (const std::exception& e) { - dump_error(e); - } - } - - std::cout << msg.str() << '\n'; - } catch (const std::exception& e) { - dump_error(e); - std::cout << winapi::address::format(address) << '\n'; - } -} - -} // namespace - -int main(int argc, char* argv[]) { - try { - Addr2Name settings{argc, argv}; - - try { - settings.parse(argc, argv); - } catch (const boost::program_options::error& e) { - settings.usage_error(e); - return 1; - } - - if (settings.exit_with_usage) { - settings.usage(); - return 0; - } - - winapi::PostMortem analysis; - - for (const auto& pdb : settings.pdbs) - analysis.add_pdb(pdb.online_base, pdb.path); - - for (const auto& address : settings.addresses) - resolve_symbol(analysis, address, settings.lines); - } catch (const std::exception& e) { - dump_error(e); - return 1; - } - return 0; -} diff --git a/utils/command_line.hpp b/utils/command_line.hpp deleted file mode 100644 index d3178f1..0000000 --- a/utils/command_line.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "winapi-debug" project. -// For details, see https://github.com/egor-tensin/winapi-debug. -// Distributed under the MIT License. - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -class SettingsParser { -public: - explicit SettingsParser(int, char** argv) : prog_name{extract_filename(argv[0])} { - visible.add_options()("help,h", "show this message and exit"); - } - - virtual ~SettingsParser() = default; - - virtual const char* get_short_description() const { - return "[--option VALUE]..."; - } - - virtual void parse(int argc, char* argv[]) { - boost::program_options::options_description all; - all.add(hidden).add(visible); - boost::program_options::variables_map vm; - boost::program_options::store(boost::program_options::command_line_parser{argc, argv} - .options(all) - .positional(positional) - .run(), - vm); - if (vm.count("help")) - exit_with_usage = true; - else - boost::program_options::notify(vm); - } - - bool exit_with_usage = false; - - void usage() const { - std::cout << *this; - } - - void usage_error(const std::exception& e) const { - std::cerr << std::format("usage error: {}\n", e.what()); - std::cerr << *this; - } - -protected: - boost::program_options::options_description hidden; - boost::program_options::options_description visible; - boost::program_options::positional_options_description positional; - -private: - static std::string extract_filename(char* path) { - return std::filesystem::path{path}.filename().string(); - } - - const std::string prog_name; - - friend std::ostream& operator<<(std::ostream& os, const SettingsParser& parser) { - const auto short_descr = parser.get_short_description(); - os << std::format("usage: {} {}\n", parser.prog_name, short_descr); - os << parser.visible; - return os; - } -}; diff --git a/utils/enum_symbols.cpp b/utils/enum_symbols.cpp deleted file mode 100644 index 645bc13..0000000 --- a/utils/enum_symbols.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "winapi-debug" project. -// For details, see https://github.com/egor-tensin/winapi-debug. -// Distributed under the MIT License. - -#include "command_line.hpp" - -#include - -#include - -#include -#include -#include -#include - -namespace { - -class EnumSymbols : public SettingsParser { -public: - explicit EnumSymbols(int argc, char** argv) : SettingsParser{argc, argv} { - namespace po = boost::program_options; - - visible.add_options()("pdb", - po::value>(&pdbs)->value_name("PATH"), - "load a PDB file"); - visible.add_options()( - "functions", - po::value(&tag)->implicit_value(function_tag)->zero_tokens(), - "only list functions"); - visible.add_options()( - "mask", po::value(&symbol_mask)->value_name("MASK"), "symbol mask"); - } - - const char* get_short_description() const override { - return "[-h|--help] [--pdb PATH]... [--functions] [--mask MASK]"; - } - - std::vector pdbs; - - bool type_specified() const { - return tag != reserved_tag; - } - - winapi::Symbol::Type get_type() const { - return static_cast(tag); - } - - std::string get_mask() const { - return symbol_mask; - } - -private: - static constexpr auto reserved_tag = - static_cast(winapi::Symbol::Type::RESERVED); - static constexpr auto function_tag = - static_cast(winapi::Symbol::Type::Function); - - winapi::symbol::Tag tag = reserved_tag; - std::string symbol_mask{winapi::DbgHelp::all_symbols}; -}; - -constexpr winapi::symbol::Tag EnumSymbols::reserved_tag; -constexpr winapi::symbol::Tag EnumSymbols::function_tag; - -} // namespace - -int main(int argc, char* argv[]) { - try { - EnumSymbols settings{argc, argv}; - - try { - settings.parse(argc, argv); - } catch (const boost::program_options::error& e) { - settings.usage_error(e); - return 1; - } - - if (settings.exit_with_usage) { - settings.usage(); - return 0; - } - - const auto dbghelp = winapi::DbgHelp::post_mortem(); - - for (const auto& pdb : settings.pdbs) { - const auto id = dbghelp.load_pdb(pdb); - - dbghelp.enum_symbols(id, settings.get_mask(), [&](const winapi::SymbolInfo& symbol) { - if (!settings.type_specified() || settings.get_type() == symbol.get_type()) - std::cout << symbol.get_name() << '\n'; - }); - } - } catch (const std::exception& e) { - std::cerr << std::format("error: {}\n", e.what()); - return 1; - } - return 0; -} diff --git a/utils/name2addr.cpp b/utils/name2addr.cpp deleted file mode 100644 index d253aa9..0000000 --- a/utils/name2addr.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "winapi-debug" project. -// For details, see https://github.com/egor-tensin/winapi-debug. -// Distributed under the MIT License. - -#include "command_line.hpp" -#include "pdb_descr.hpp" - -#include - -#include - -#include -#include -#include -#include -#include - -namespace { - -class Name2Addr : public SettingsParser { -public: - explicit Name2Addr(int argc, char** argv) : SettingsParser{argc, argv} { - namespace po = boost::program_options; - - visible.add_options()( - "pdb", po::value>(&pdbs)->value_name("ADDR,PATH"), "load a PDB file"); - hidden.add_options()("name", - po::value>(&names)->value_name("NAME"), - "add a name to resolve"); - positional.add("name", -1); - } - - const char* get_short_description() const override { - return "[-h|--help] [--pdb ADDR,PATH]... [--] [NAME]..."; - } - - std::vector pdbs; - std::vector names; -}; - -void dump_error(const std::exception& e) { - std::cerr << std::format("error: {}\n", e.what()); -} - -void resolve_symbol(const winapi::PostMortem& analysis, std::string_view name) { - try { - const auto address = analysis.resolve_symbol(name).get_online_address(); - std::cout << winapi::address::format(address) << '\n'; - } catch (const std::exception& e) { - dump_error(e); - std::cout << name << '\n'; - } -} - -} // namespace - -int main(int argc, char* argv[]) { - try { - Name2Addr settings{argc, argv}; - - try { - settings.parse(argc, argv); - } catch (const boost::program_options::error& e) { - settings.usage_error(e); - return 1; - } - - if (settings.exit_with_usage) { - settings.usage(); - return 0; - } - - winapi::PostMortem analysis; - - for (const auto& pdb : settings.pdbs) - analysis.add_pdb(pdb.online_base, pdb.path); - - for (const auto& name : settings.names) - resolve_symbol(analysis, name); - } catch (const std::exception& e) { - dump_error(e); - return 1; - } - return 0; -} diff --git a/utils/pdb_descr.hpp b/utils/pdb_descr.hpp deleted file mode 100644 index c2e720a..0000000 --- a/utils/pdb_descr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "winapi-debug" project. -// For details, see https://github.com/egor-tensin/winapi-debug. -// Distributed under the MIT License. - -#pragma once - -#include - -#include - -#include -#include - -struct PDB { - winapi::Address online_base; - std::string path; - - static PDB parse(const std::string& src) { - static constexpr auto sep = ','; - - const auto sep_pos = src.find(sep); - if (sep_pos == std::string::npos) - throw boost::program_options::invalid_option_value{src}; - - winapi::Address online_base; - if (!winapi::address::parse(online_base, src.substr(0, sep_pos))) - throw boost::program_options::invalid_option_value{src}; - - return {online_base, src.substr(sep_pos + 1)}; - } - - static winapi::Address parse_address(const std::string& src) { - winapi::Address dest; - if (!winapi::address::parse(dest, src)) - throw boost::program_options::invalid_option_value{src}; - return dest; - } -}; - -template -void validate(boost::any& dest, - const std::vector>& src_tokens, - PDB*, - int) { - namespace po = boost::program_options; - po::validators::check_first_occurrence(dest); - const auto& src_token = po::validators::get_single_string(src_tokens); - dest = boost::any{PDB::parse(src_token)}; -} - -template -void validate(boost::any& dest, - const std::vector>& src_tokens, - winapi::Address*, - int) { - namespace po = boost::program_options; - po::validators::check_first_occurrence(dest); - const auto& src_token = po::validators::get_single_string(src_tokens); - dest = boost::any{PDB::parse_address(src_token)}; -} -- cgit v1.3