Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(796)

Unified Diff: tools/traceline/traceline/sym_resolver.h

Issue 20494: Import Traceline, a Windows performance trace event logger. (Closed)
Patch Set: Feedback. Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/traceline/traceline/stubs.asm ('k') | tools/traceline/traceline/syscall_map.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_
« no previous file with comments | « tools/traceline/traceline/stubs.asm ('k') | tools/traceline/traceline/syscall_map.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698