Index: tools/traceline/traceline/sym_resolver.h |
diff --git a/tools/traceline/traceline/sym_resolver.h b/tools/traceline/traceline/sym_resolver.h |
new file mode 100755 |
index 0000000000000000000000000000000000000000..53948b0c443e7b3e6b6fc7ffbe1da8e833f0ecda |
--- /dev/null |
+++ b/tools/traceline/traceline/sym_resolver.h |
@@ -0,0 +1,163 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// A smaller wrapper around the dbghelp symbol resolution routines. |
+// For example: |
+// SymResolver resolver("ntdll.dll"); |
+// resolver.Resolve("ntdll!NtBlahBlah"); |
+ |
+#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: |
+ |
+ // Constructor to load a single DLL. |
+ SymResolver(const char* dllname, HANDLE proc = ::GetCurrentProcess()) |
+ : proc_(proc) { |
+ |
+ // TODO(deanm): Would be nice to get this from WinDBG, but it's buried |
+ // in the workspace data blob... _NT_SYMBOL_PATH is not usually set... |
+ static char* kSymbolPath = |
+ "C:\\Program Files\\Debugging Tools for Windows (x86)\\sym;" |
+ "C:\\Program Files\\Debugging Tools for Windows\\sym"; |
+ |
+ // If we want to load a specific DLL, or we want to load all. |
+ 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; |
+ // The name returned from SymEnumerateModules64 doesn't include the ext, |
+ // so we can't differentiate between a dll and exe of the same name. So |
+ // collect all of the base addresses and query for more info. |
+ if (SymEnumerateModules64(proc_, &SymEnumer, &bases) != TRUE) { |
+ NOTREACHED("SymEnumerateModules64 failed: %d\n", GetLastError()); |
+ } |
+ for (size_t i = 0; i < bases.size(); ++i) { |
+ // This was failing, turns out I was just using the system32 |
+ // dbghelp.dll which is old, use the one from windbg :( |
+ 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); |
+ |
+ // Map the base address to the image name... |
+ dlls_[static_cast<int>(bases[i])] = filename; |
+ } |
+ |
+ // TODO(deanm): check the symbols are rad and stuff... |
+ } |
+ |
+ char* Resolve(const char* name) { |
+ // The API writes to the space after SYMBOL_INFO... |
+ 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) { |
+ // The API writes to the space after SYMBOL_INFO... |
+ 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 // TRACELINE_SYM_RESOLVER_H_ |