aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/utils/addr2name.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/addr2name.cpp')
-rw-r--r--src/utils/addr2name.cpp119
1 files changed, 119 insertions, 0 deletions
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 <Egor.Tensin@gmail.com>
+// 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 <winapi/debug.hpp>
+
+#include <boost/program_options.hpp>
+
+#include <exception>
+#include <format>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+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<std::vector<PDB>>(&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<std::vector<winapi::Address>>(&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<PDB> pdbs;
+ std::vector<winapi::Address> 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;
+}