This source file includes following definitions.
- SymEnumer
#ifndef TRACELINE_SYM_RESOLVER_H_
#define TRACELINE_SYM_RESOLVER_H_
#include <windows.h>
#include <dbghelp.h>
#include <vector>
#include <string>
#include <map>
static BOOL CALLBACK SymEnumer(PCSTR name, DWORD64 base, PVOID context) {
reinterpret_cast<std::vector<DWORD64>*>(context)->push_back(base);
return TRUE;
}
class SymResolver {
public:
SymResolver(const char* dllname, HANDLE proc = ::GetCurrentProcess())
: proc_(proc) {
static char* kSymbolPath =
"C:\\Program Files\\Debugging Tools for Windows (x86)\\sym;"
"C:\\Program Files\\Debugging Tools for Windows\\sym";
if (::SymInitialize(proc_, kSymbolPath, dllname ? FALSE : TRUE) != TRUE) {
NOTREACHED("SymInitialize failed: %d", GetLastError());
}
base_ = 0;
if (dllname) {
base_ = ::SymLoadModuleEx(proc_,
NULL,
const_cast<char*>(dllname),
NULL,
reinterpret_cast<DWORD64>(
GetModuleHandleA(dllname)),
0,
NULL,
0);
if (base_ == 0) {
NOTREACHED("SymLoadModuleEx(%s) failed: %d", dllname, GetLastError());
}
}
std::vector<DWORD64> bases;
PSYM_ENUMMODULES_CALLBACK64 enumer =
reinterpret_cast<PSYM_ENUMMODULES_CALLBACK64>(&SymEnumer);
if (SymEnumerateModules64(proc_, enumer, &bases) != TRUE) {
NOTREACHED("SymEnumerateModules64 failed: %d\n", GetLastError());
}
for (size_t i = 0; i < bases.size(); ++i) {
IMAGEHLP_MODULE64 info;
info.SizeOfStruct = sizeof(info);
if (SymGetModuleInfo64(proc_, bases[i], &info) != TRUE) {
NOTREACHED("SymGetModuleInfo64 failed: %d\n", GetLastError());
}
std::string filename(info.ImageName);
size_t last_slash = filename.find_last_of('\\');
if (last_slash != std::string::npos)
filename = filename.substr(filename.find_last_of('\\') + 1);
dlls_[static_cast<int>(bases[i])] = filename;
}
}
char* Resolve(const char* name) {
struct {
SYMBOL_INFO info;
char buf[128];
} info = {0};
info.info.SizeOfStruct = sizeof(info.info);
info.info.ModBase = base_;
info.info.MaxNameLen = 127;
if (SymFromName(proc_, const_cast<char*>(name), &info.info) != TRUE) {
NOTREACHED("SymFromName(%s) failed: %d", name, GetLastError());
}
return reinterpret_cast<char*>(info.info.Address);
}
std::string Unresolve(int ptr) {
struct {
SYMBOL_INFO info;
char buf[128];
} info = {0};
info.info.SizeOfStruct = sizeof(info.info);
info.info.ModBase = base_;
info.info.MaxNameLen = 127;
if (!::SymFromAddr(proc_, static_cast<DWORD64>(ptr), NULL, &info.info)) {
return std::string("failed");
}
std::string name;
int addr = static_cast<int>(info.info.Address);
int base = static_cast<int>(info.info.ModBase);
if (dlls_.count(base) == 1) {
name.append(dlls_[base]);
} else {
name.append("unknown_mod");
}
name.push_back('!');
name.append(info.info.Name);
char buf[32];
_itoa_s(ptr - addr, buf, sizeof(buf), 16);
name.append("+0x");
name.append(buf);
DWORD disp;
IMAGEHLP_LINE64 line;
if (::SymGetLineFromAddr64(
proc_, static_cast<DWORD64>(ptr), &disp, &line)) {
name.append(" [ ");
name.append(line.FileName);
name.append(":");
_itoa_s(line.LineNumber, buf, sizeof(buf), 10);
name.append(buf);
name.append(" ]");
}
return name;
}
~SymResolver() {
if (::SymCleanup(proc_) != TRUE) {
NOTREACHED("SymCleanup failed: %d", GetLastError());
}
}
private:
HANDLE proc_;
ULONG64 base_;
std::map<int, std::string> dlls_;
};
#endif