aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--utils/CMakeLists.txt14
-rw-r--r--utils/addr2name.cpp130
-rw-r--r--utils/command_line.hpp86
-rw-r--r--utils/enum_symbols.cpp117
-rw-r--r--utils/name2addr.cpp132
-rw-r--r--utils/pdb_descr.hpp86
6 files changed, 565 insertions, 0 deletions
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
new file mode 100644
index 0000000..60f5b9f
--- /dev/null
+++ b/utils/CMakeLists.txt
@@ -0,0 +1,14 @@
+find_package(Boost REQUIRED COMPONENTS filesystem program_options system)
+
+add_executable(enum_symbols enum_symbols.cpp command_line.hpp pdb_descr.hpp)
+target_compile_definitions(enum_symbols PRIVATE _NO_CVCONST_H)
+target_include_directories(enum_symbols SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
+target_link_libraries(enum_symbols PRIVATE pdb_repo ${Boost_LIBRARIES})
+
+add_executable(name2addr name2addr.cpp)
+target_include_directories(name2addr SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
+target_link_libraries(name2addr PRIVATE pdb_repo ${Boost_LIBRARIES})
+
+add_executable(addr2name addr2name.cpp command_line.hpp pdb_descr.hpp)
+target_include_directories(addr2name SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
+target_link_libraries(addr2name PRIVATE pdb_repo ${Boost_LIBRARIES})
diff --git a/utils/addr2name.cpp b/utils/addr2name.cpp
new file mode 100644
index 0000000..a01f61e
--- /dev/null
+++ b/utils/addr2name.cpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2017 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "PDB repository" project.
+// For details, see https://github.com/egor-tensin/pdb-repo.
+// Distributed under the MIT License.
+
+#include "command_line.hpp"
+#include "pdb_descr.hpp"
+
+#include "pdb/all.hpp"
+
+#include <boost/program_options.hpp>
+
+#include <exception>
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace
+{
+ class Addr2Name : public SettingsParser
+ {
+ public:
+ explicit Addr2Name(const std::string& argv0)
+ : SettingsParser{argv0, build_options(), build_args()}
+ { }
+
+ bool exit_with_usage() const { return help_flag; }
+
+ const char* get_short_description() const override
+ {
+ return "[-h|--help] [--pdb ADDR,PATH]... [--] [ADDR]...";
+ }
+
+ std::vector<PDB> pdbs;
+
+ std::vector<pdb::Address> addresses;
+
+ private:
+ Options build_options()
+ {
+ namespace program_options = boost::program_options;
+ Options descr{"options"};
+ descr.add_options()
+ ("help,h",
+ program_options::bool_switch(&help_flag),
+ "show this message and exit")
+ ("pdb",
+ program_options::value<std::vector<PDB>>(&pdbs)
+ ->value_name("ADDR,PATH"),
+ "load a PDB file")
+ ("address",
+ program_options::value<std::vector<pdb::Address>>(&addresses)
+ ->value_name("ADDR"),
+ "add an address to resolve");
+ return descr;
+ }
+
+ static Arguments build_args()
+ {
+ Arguments descr;
+ descr.add("address", -1);
+ return descr;
+ }
+
+ bool help_flag = false;
+ };
+
+ std::string format_address(pdb::Address address)
+ {
+ std::ostringstream oss;
+ oss << std::showbase << std::hex << address;
+ return oss.str();
+ }
+
+ void dump_error(const std::exception& e)
+ {
+ std::cerr << "error: " << e.what() << '\n';
+ }
+
+ void resolve_symbol(const pdb::Repo& repo, pdb::Address address)
+ {
+ try
+ {
+ std::cout << repo.resolve_symbol(address).get_name() << '\n';
+ }
+ catch (const std::exception& e)
+ {
+ dump_error(e);
+ std::cout << format_address(address) << '\n';
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ const Addr2Name settings{argv[0]};
+
+ 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;
+ }
+
+ pdb::Repo repo;
+
+ for (const auto& pdb : settings.pdbs)
+ repo.add_pdb(pdb.online_base, pdb.path);
+
+ for (const auto& address : settings.addresses)
+ resolve_symbol(repo, address);
+ }
+ catch (const std::exception& e)
+ {
+ dump_error(e);
+ return 1;
+ }
+ return 0;
+}
diff --git a/utils/command_line.hpp b/utils/command_line.hpp
new file mode 100644
index 0000000..79fb673
--- /dev/null
+++ b/utils/command_line.hpp
@@ -0,0 +1,86 @@
+// Copyright (c) 2017 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "PDB repository" project.
+// For details, see https://github.com/egor-tensin/pdb-repo.
+// Distributed under the MIT License.
+
+#pragma once
+
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+
+#include <exception>
+#include <iostream>
+#include <ostream>
+#include <string>
+
+namespace
+{
+ class SettingsParser
+ {
+ public:
+ typedef boost::program_options::options_description Options;
+ typedef boost::program_options::positional_options_description Arguments;
+
+ explicit SettingsParser(const std::string& argv0)
+ : prog_name{extract_filename(argv0)}
+ { }
+
+ SettingsParser(const std::string& argv0, const Options& options)
+ : prog_name{extract_filename(argv0)}
+ , options{options}
+ { }
+
+ SettingsParser(const std::string& argv0, const Options& options, const Arguments& args)
+ : prog_name{extract_filename(argv0)}
+ , options{options}
+ , args{args}
+ { }
+
+ virtual ~SettingsParser() = default;
+
+ virtual const char* get_short_description() const { return "[OPTION]..."; }
+
+ void parse(int argc, char* argv[]) const
+ {
+ boost::program_options::variables_map vm;
+ boost::program_options::store(
+ boost::program_options::command_line_parser{argc, argv}
+ .options(options)
+ .positional(args)
+ .run(),
+ vm);
+ boost::program_options::notify(vm);
+ }
+
+ void usage() const
+ {
+ std::cout << *this;
+ }
+
+ void usage_error(const std::exception& e) const
+ {
+ std::cerr << "usage error: " << e.what() << '\n';
+ std::cerr << *this;
+ }
+
+ private:
+ static std::string extract_filename(const std::string& path)
+ {
+ return boost::filesystem::path{path}.filename().string();
+ }
+
+ const std::string prog_name;
+ const Options options;
+ const Arguments args;
+
+ friend std::ostream& operator<<(std::ostream&, const SettingsParser&);
+ };
+
+ std::ostream& operator<<(std::ostream& os, const SettingsParser& cmd_parser)
+ {
+ const auto short_descr = cmd_parser.get_short_description();
+ os << "usage: " << cmd_parser.prog_name << ' ' << short_descr << '\n';
+ os << cmd_parser.options;
+ return os;
+ }
+}
diff --git a/utils/enum_symbols.cpp b/utils/enum_symbols.cpp
new file mode 100644
index 0000000..d7fd417
--- /dev/null
+++ b/utils/enum_symbols.cpp
@@ -0,0 +1,117 @@
+// Copyright (c) 2017 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "PDB repository" project.
+// For details, see https://github.com/egor-tensin/pdb-repo.
+// Distributed under the MIT License.
+
+#include "command_line.hpp"
+#include "pdb_descr.hpp"
+
+#include "pdb/all.hpp"
+
+#include <boost/program_options.hpp>
+
+#include <exception>
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace
+{
+ class EnumSymbols : public SettingsParser
+ {
+ public:
+ explicit EnumSymbols(const std::string& argv0)
+ : SettingsParser{argv0, build_options()}
+ { }
+
+ bool exit_with_usage() const { return help_flag; }
+
+ const char* get_short_description() const override
+ {
+ return "[-h|--help] [--pdb ADDR,PATH]... [--functions]";
+ }
+
+ std::vector<PDB> pdbs;
+
+ bool type_specified() const
+ {
+ return tag != reserved_tag;
+ }
+
+ pdb::Symbol::Type get_type() const
+ {
+ return static_cast<pdb::Symbol::Type>(tag);
+ }
+
+ private:
+ Options build_options()
+ {
+ namespace program_options = boost::program_options;
+ Options descr{"options"};
+ descr.add_options()
+ ("help,h",
+ program_options::bool_switch(&help_flag),
+ "show this message and exit")
+ ("pdb",
+ program_options::value<std::vector<PDB>>(&pdbs)
+ ->value_name("ADDR,PATH"),
+ "load a PDB file")
+ ("functions",
+ program_options::value<pdb::Symbol::Tag>(&tag)
+ ->implicit_value(function_tag)
+ ->zero_tokens(),
+ "only list functions");
+ return descr;
+ }
+
+ bool help_flag = false;
+
+ static const auto reserved_tag = static_cast<pdb::Symbol::Tag>(pdb::Symbol::Type::RESERVED);
+ static const auto function_tag = static_cast<pdb::Symbol::Tag>(pdb::Symbol::Type::Function);
+
+ pdb::Symbol::Tag tag = reserved_tag;
+ };
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ const EnumSymbols settings{argv[0]};
+
+ 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;
+ }
+
+ pdb::Repo repo;
+
+ for (const auto& pdb : settings.pdbs)
+ {
+ const auto id = repo.add_pdb(pdb.online_base, pdb.path);
+
+ repo.enum_symbols(id, [&] (const pdb::Symbol& symbol)
+ {
+ if (!settings.type_specified() || settings.get_type() == symbol.get_type())
+ std::cout << symbol.get_name() << '\n';
+ });
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "error: " << e.what() << '\n';
+ return 1;
+ }
+ return 0;
+}
diff --git a/utils/name2addr.cpp b/utils/name2addr.cpp
new file mode 100644
index 0000000..055b469
--- /dev/null
+++ b/utils/name2addr.cpp
@@ -0,0 +1,132 @@
+// Copyright (c) 2017 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "PDB repository" project.
+// For details, see https://github.com/egor-tensin/pdb-repo.
+// Distributed under the MIT License.
+
+#include "command_line.hpp"
+#include "pdb_descr.hpp"
+
+#include "pdb/all.hpp"
+
+#include <boost/program_options.hpp>
+
+#include <exception>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace
+{
+ class Name2Addr : public SettingsParser
+ {
+ public:
+ explicit Name2Addr(const std::string& argv0)
+ : SettingsParser{argv0, build_options(), build_args()}
+ { }
+
+ bool exit_with_usage() const { return help_flag; }
+
+ const char* get_short_description() const override
+ {
+ return "[-h|--help] [--pdb ADDR,PATH]... [--] [NAME]...";
+ }
+
+ std::vector<PDB> pdbs;
+
+ std::vector<std::string> names;
+
+ private:
+ Options build_options()
+ {
+ namespace program_options = boost::program_options;
+ Options descr{"options"};
+ descr.add_options()
+ ("help,h",
+ program_options::bool_switch(&help_flag),
+ "show this message and exit")
+ ("pdb",
+ program_options::value<std::vector<PDB>>(&pdbs)
+ ->value_name("ADDR,PATH"),
+ "load a PDB file")
+ ("name",
+ program_options::value<std::vector<std::string>>(&names)
+ ->value_name("NAME"),
+ "add a name to resolve");
+ return descr;
+ }
+
+ static Arguments build_args()
+ {
+ Arguments descr;
+ descr.add("name", -1);
+ return descr;
+ }
+
+ bool help_flag = false;
+ };
+
+ std::string format_address(pdb::Address address)
+ {
+ std::ostringstream oss;
+ oss << std::showbase << std::hex << address;
+ return oss.str();
+ }
+
+ void dump_error(const std::exception& e)
+ {
+ std::cerr << "error: " << e.what() << '\n';
+ }
+
+ void resolve_symbol(const pdb::Repo& repo, const std::string& name)
+ {
+ try
+ {
+ const auto address = repo.resolve_symbol(name).get_online_address();
+ std::cout << format_address(address) << '\n';
+ }
+ catch (const std::exception& e)
+ {
+ dump_error(e);
+ std::cout << name << '\n';
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ const Name2Addr settings{argv[0]};
+
+ 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;
+ }
+
+ pdb::Repo repo;
+
+ for (const auto& pdb : settings.pdbs)
+ repo.add_pdb(pdb.online_base, pdb.path);
+
+ for (const auto& name : settings.names)
+ resolve_symbol(repo, 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
new file mode 100644
index 0000000..c57a0e9
--- /dev/null
+++ b/utils/pdb_descr.hpp
@@ -0,0 +1,86 @@
+// Copyright (c) 2017 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "PDB repository" project.
+// For details, see https://github.com/egor-tensin/pdb-repo.
+// Distributed under the MIT License.
+
+#pragma once
+
+#include "pdb/all.hpp"
+
+#include <boost/program_options.hpp>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace
+{
+ struct PDB
+ {
+ PDB(pdb::Address online_base, const std::string& path)
+ : online_base{online_base}
+ , path{path}
+ { }
+
+ pdb::Address online_base;
+ std::string path;
+
+ static PDB parse(std::string src)
+ {
+ static constexpr auto sep = ',';
+ const auto sep_pos = src.find(sep);
+ if (sep_pos == std::string::npos)
+ boost::throw_exception(boost::program_options::invalid_option_value{src});
+ pdb::Address online_base;
+ if (!parse_address(online_base, src.substr(0, sep_pos)))
+ boost::throw_exception(boost::program_options::invalid_option_value{src});
+ return {online_base, src.substr(sep_pos + 1)};
+ }
+
+ static bool parse_address(pdb::Address& dest, const std::string& src)
+ {
+ std::istringstream iss{src};
+ iss >> std::hex;
+ char c;
+ return iss >> dest && !iss.get(c);
+ }
+
+ static pdb::Address parse_address(const std::string& src)
+ {
+ pdb::Address dest;
+ if (!parse_address(dest, src))
+ boost::throw_exception(boost::program_options::invalid_option_value{src});
+ return dest;
+ }
+ };
+}
+
+namespace boost
+{
+ namespace program_options
+ {
+ template <typename charT>
+ void validate(
+ boost::any& dest,
+ const std::vector<std::basic_string<charT>>& src_tokens,
+ PDB*,
+ int)
+ {
+ validators::check_first_occurrence(dest);
+ const auto& src_token = validators::get_single_string(src_tokens);
+ dest = any{PDB::parse(src_token)};
+ }
+
+ template <typename charT>
+ void validate(
+ boost::any& dest,
+ const std::vector<std::basic_string<charT>>& src_tokens,
+ pdb::Address*,
+ int)
+ {
+ validators::check_first_occurrence(dest);
+ const auto& src_token = validators::get_single_string(src_tokens);
+ dest = any{PDB::parse_address(src_token)};
+ }
+ }
+}