aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/repo.cpp
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2017-05-17 06:00:20 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2017-05-17 06:00:20 +0300
commitc67055bad3cdfc93e2ac57d87f36c6e0993af690 (patch)
treeda8759c66f1af00415784e5824e6bfc2195aee92 /src/repo.cpp
downloadwinapi-debug-c67055bad3cdfc93e2ac57d87f36c6e0993af690.tar.gz
winapi-debug-c67055bad3cdfc93e2ac57d87f36c6e0993af690.zip
initial commit
Diffstat (limited to 'src/repo.cpp')
-rw-r--r--src/repo.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/repo.cpp b/src/repo.cpp
new file mode 100644
index 0000000..0b28d5e
--- /dev/null
+++ b/src/repo.cpp
@@ -0,0 +1,128 @@
+// 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 "pdb/all.hpp"
+
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+namespace pdb
+{
+ namespace
+ {
+ template <typename Value>
+ const Module& guess_module(
+ const std::map<Address, Value>& modules,
+ Address pivot)
+ {
+ if (modules.empty())
+ throw std::range_error{"there're no modules to choose from"};
+
+ auto it = modules.lower_bound(pivot);
+
+ if (it == modules.cend())
+ {
+ --it;
+ return it->second;
+ }
+
+ if (it->first > pivot)
+ {
+ if (it == modules.cbegin())
+ throw std::range_error{"couldn't choose a module"};
+ --it;
+ return it->second;
+ }
+
+ return it->second;
+ }
+
+ Address address_online_to_offline(const Module& module, Address online)
+ {
+ return module.get_offline_base() + online - module.get_online_base();
+ }
+
+ Address address_offline_to_online(const Module& module, Address offline)
+ {
+ return module.get_online_base() + offline - module.get_offline_base();
+ }
+ }
+
+ Address Repo::add_pdb(Address online_base, const std::string& path)
+ {
+ Module module{online_base, dbghelp.load_pdb(path)};
+ const auto offline_base = module.get_offline_base();
+ const auto it = online_modules.emplace(online_base, std::move(module));
+ offline_modules.emplace(offline_base, it.first->second);
+ return offline_base;
+ }
+
+ void Repo::enum_symbols(const OnSymbol& callback) const
+ {
+ for (const auto& it : offline_modules)
+ enum_symbols(it.second, callback);
+ }
+
+ void Repo::enum_symbols(Address offline_base, const OnSymbol& callback) const
+ {
+ const auto it = offline_modules.find(offline_base);
+ if (it == offline_modules.cend())
+ throw std::runtime_error{"unknown module"};
+ enum_symbols(it->second, callback);
+ }
+
+ void Repo::enum_symbols(const Module& module, const OnSymbol& callback) const
+ {
+ dbghelp.enum_symbols(module, [&] (const SymbolInfo& raw)
+ {
+ callback(symbol_from_buffer(module, raw));
+ });
+ }
+
+ Symbol Repo::resolve_symbol(Address online) const
+ {
+ return symbol_from_buffer(dbghelp.resolve_symbol(address_online_to_offline(online)));
+ }
+
+ Symbol Repo::resolve_symbol(const std::string& name) const
+ {
+ return symbol_from_buffer(dbghelp.resolve_symbol(name));
+ }
+
+ Symbol Repo::symbol_from_buffer(const SymbolInfo& raw) const
+ {
+ const auto it = offline_modules.find(raw.get_offline_base());
+ if (it == offline_modules.cend())
+ throw std::runtime_error{"symbol's module is unknown"};
+ return symbol_from_buffer(it->second, raw);
+ }
+
+ Symbol Repo::symbol_from_buffer(const Module& module, const SymbolInfo& raw) const
+ {
+ return {pdb::address_offline_to_online(module, raw.get_offline_address()), raw};
+ }
+
+ Address Repo::address_online_to_offline(Address online) const
+ {
+ return pdb::address_online_to_offline(module_from_online_address(online), online);
+ }
+
+ Address Repo::address_offline_to_online(Address offline) const
+ {
+ return pdb::address_offline_to_online(module_from_offline_address(offline), offline);
+ }
+
+ const Module& Repo::module_from_online_address(Address online) const
+ {
+ return guess_module(online_modules, online);
+ }
+
+ const Module& Repo::module_from_offline_address(Address offline) const
+ {
+ return guess_module(offline_modules, offline);
+ }
+}