diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2017-05-22 02:10:22 +0300 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2017-05-22 02:10:22 +0300 |
commit | b6919562ab09fc18dfa90c4588636b4f6ffcd76c (patch) | |
tree | ecfba51bb575e02a28d2224f557eca34eca7c8fc | |
parent | addr2name: include module names (diff) | |
download | winapi-debug-b6919562ab09fc18dfa90c4588636b4f6ffcd76c.tar.gz winapi-debug-b6919562ab09fc18dfa90c4588636b4f6ffcd76c.zip |
add line numbers to symbols
-rw-r--r-- | include/pdb/dbghelp.hpp | 2 | ||||
-rw-r--r-- | include/pdb/repo.hpp | 2 | ||||
-rw-r--r-- | include/pdb/symbol.hpp | 25 | ||||
-rw-r--r-- | src/dbghelp.cpp | 32 | ||||
-rw-r--r-- | src/repo.cpp | 5 | ||||
-rw-r--r-- | utils/addr2name.cpp | 36 |
6 files changed, 93 insertions, 9 deletions
diff --git a/include/pdb/dbghelp.hpp b/include/pdb/dbghelp.hpp index d6b6899..2555de1 100644 --- a/include/pdb/dbghelp.hpp +++ b/include/pdb/dbghelp.hpp @@ -32,6 +32,8 @@ namespace pdb SymbolInfo resolve_symbol(Address) const; SymbolInfo resolve_symbol(const std::string&) const; + LineInfo resolve_line(Address) const; + private: ModuleInfo get_module_info(Address offline_base) const; diff --git a/include/pdb/repo.hpp b/include/pdb/repo.hpp index dd41b17..c8a2964 100644 --- a/include/pdb/repo.hpp +++ b/include/pdb/repo.hpp @@ -33,6 +33,8 @@ namespace pdb Symbol resolve_symbol(Address) const; Symbol resolve_symbol(const std::string&) const; + LineInfo resolve_line(Address) const; + const Module& module_with_online_base(Address) const; const Module& module_with_offline_base(Address) const; diff --git a/include/pdb/symbol.hpp b/include/pdb/symbol.hpp index fc200c7..81a40e3 100644 --- a/include/pdb/symbol.hpp +++ b/include/pdb/symbol.hpp @@ -111,4 +111,29 @@ namespace pdb private: const Address online_address; }; + + class LineInfo + { + public: + typedef IMAGEHLP_LINE64 Raw; + + explicit LineInfo(const Raw& raw) + : file_path{raw.FileName} + , line_number{cast_line_number(raw.LineNumber)} + { } + + const std::string file_path; + const unsigned long line_number; + + private: + static unsigned long cast_line_number(DWORD raw) + { + unsigned long dest = 0; + + if (!msl::utilities::SafeCast(raw, dest)) + throw std::runtime_error{"invalid line number"}; + + return dest; + } + }; } diff --git a/src/dbghelp.cpp b/src/dbghelp.cpp index 30829d4..0a78e4d 100644 --- a/src/dbghelp.cpp +++ b/src/dbghelp.cpp @@ -11,6 +11,7 @@ #include <DbgHelp.h> #include <cstddef> +#include <cstring> #include <stdexcept> #include <string> @@ -19,14 +20,17 @@ namespace pdb { namespace { - void enable_debug_output() + void set_dbghelp_options() { - SymSetOptions(SymGetOptions() | SYMOPT_DEBUG | SYMOPT_UNDNAME); + SymSetOptions(SymGetOptions() + | SYMOPT_DEBUG + | SYMOPT_LOAD_LINES + | SYMOPT_UNDNAME); } void initialize(HANDLE id) { - enable_debug_output(); + set_dbghelp_options(); if (!SymInitialize(id, NULL, FALSE)) throw error::windows(GetLastError()); @@ -129,14 +133,14 @@ namespace pdb throw error::windows(GetLastError()); } - SymbolInfo DbgHelp::resolve_symbol(Address online) const + SymbolInfo DbgHelp::resolve_symbol(Address offline) const { Address displacement = 0; SymbolInfo symbol; if (!SymFromAddr( id, - online, + offline, &displacement, &static_cast<SYMBOL_INFO&>(symbol))) throw error::windows(GetLastError()); @@ -157,4 +161,22 @@ namespace pdb return symbol; } + + LineInfo DbgHelp::resolve_line(Address offline) const + { + IMAGEHLP_LINE64 raw; + std::memset(&raw, 0, sizeof(raw)); + raw.SizeOfStruct = sizeof(raw); + + DWORD displacement = 0; + + if (!SymGetLineFromAddr64( + id, + offline, + &displacement, + &raw)) + throw error::windows(GetLastError()); + + return LineInfo{raw}; + } } diff --git a/src/repo.cpp b/src/repo.cpp index edd62d5..7a19c83 100644 --- a/src/repo.cpp +++ b/src/repo.cpp @@ -155,6 +155,11 @@ namespace pdb return symbol_from_buffer(dbghelp.resolve_symbol(name)); } + LineInfo Repo::resolve_line(Address online) const + { + return dbghelp.resolve_line(address_online_to_offline(online)); + } + const Module& Repo::module_with_online_base(Address base) const { return lookup_module(online_bases, base); diff --git a/utils/addr2name.cpp b/utils/addr2name.cpp index d611bac..b2f0a51 100644 --- a/utils/addr2name.cpp +++ b/utils/addr2name.cpp @@ -34,6 +34,7 @@ namespace std::vector<PDB> pdbs; std::vector<pdb::Address> addresses; + bool lines = false; private: Options build_options() @@ -51,7 +52,10 @@ namespace ("address", program_options::value<std::vector<pdb::Address>>(&addresses) ->value_name("ADDR"), - "add an address to resolve"); + "add an address to resolve") + ("lines,l", + program_options::bool_switch(&lines), + "try to resolve source files & line numbers"); return descr; } @@ -75,18 +79,42 @@ namespace return oss.str(); } + std::string format_line_info(const pdb::LineInfo& line_info) + { + std::ostringstream oss; + oss << '[' << line_info.file_path << " @ " << line_info.line_number << ']'; + 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) + void resolve_symbol(const pdb::Repo& repo, pdb::Address address, bool lines = false) { try { const auto symbol = repo.resolve_symbol(address); const auto& module = repo.module_with_offline_base(symbol.get_offline_base()); - std::cout << format_symbol(module, symbol) << '\n'; + + std::ostringstream msg; + msg << format_symbol(module, symbol); + + if (lines) + { + try + { + const auto line_info = repo.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) { @@ -124,7 +152,7 @@ int main(int argc, char* argv[]) repo.add_pdb(pdb.online_base, pdb.path); for (const auto& address : settings.addresses) - resolve_symbol(repo, address); + resolve_symbol(repo, address, settings.lines); } catch (const std::exception& e) { |