Index: tools/win/RetrieveSymbols/RetrieveSymbols.cpp |
diff --git a/tools/win/RetrieveSymbols/RetrieveSymbols.cpp b/tools/win/RetrieveSymbols/RetrieveSymbols.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f183673f2879e2a492fbcb28b32882c9f2249c61 |
--- /dev/null |
+++ b/tools/win/RetrieveSymbols/RetrieveSymbols.cpp |
@@ -0,0 +1,162 @@ |
+// Copyright 2014 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. |
+ |
+// Symbol downloading demonstration code. |
+// For more information see ReadMe.txt and this blog post: |
+// https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/ |
+ |
+#include <stdio.h> |
+#include <Windows.h> |
+#include <DbgHelp.h> |
+#include <string> |
+ |
+// Link with the dbghelp import library |
+#pragma comment(lib, "dbghelp.lib") |
+ |
+// Uncomment this line to test with known-good parameters. |
+//#define TESTING |
+ |
+int main(int argc, char* argv[]) |
+{ |
+ // Tell dbghelp to print diagnostics to the debugger output. |
+ SymSetOptions(SYMOPT_DEBUG); |
+ |
+ // Initialize dbghelp |
+ const HANDLE fakeProcess = (HANDLE)1; |
+ BOOL result = SymInitialize(fakeProcess, NULL, FALSE); |
+ |
+#ifdef TESTING |
+ // Set a search path and cache directory. If this isn't set |
+ // then _NT_SYMBOL_PATH will be used instead. |
+ // Force setting it here to make sure that the test succeeds. |
+ SymSetSearchPath(fakeProcess, |
+ "SRV*c:\\symbolstest*http://msdl.microsoft.com/download/symbols"); |
+ |
+ // Valid PDB data to test the code. |
+ std::string gTextArg = "072FF0EB54D24DFAAE9D13885486EE09"; |
+ const char* ageText = "2"; |
+ const char* fileName = "kernel32.pdb"; |
+ |
+ // Valid PE data to test the code |
+ fileName = "crypt32.dll"; |
+ const char* dateStampText = "4802A0D7"; |
+ const char* sizeText = "95000"; |
+ //fileName = "chrome_child.dll"; |
+ //const char* dateStampText = "5420D824"; |
+ //const char* sizeText = "20a6000"; |
+#else |
+ if (argc < 4) |
+ { |
+ printf("Error: insufficient arguments.\n"); |
+ printf("Usage: %s guid age pdbname\n", argv[0]); |
+ printf("Usage: %s dateStamp size pename\n", argv[0]); |
+ printf("Example: %s 6720c31f4ac24f3ab0243e0641a4412f 1 " |
+ "chrome_child.dll.pdb\n", argv[0]); |
+ printf("Example: %s 4802A0D7 95000 crypt32.dll\n", argv[0]); |
+ return 0; |
+ } |
+ |
+ std::string gTextArg = argv[1]; |
+ const char* dateStampText = argv[1]; |
+ const char* ageText = argv[2]; |
+ const char* sizeText = argv[2]; |
+ const char* fileName = argv[3]; |
+#endif |
+ |
+ // Parse the GUID and age from the text |
+ GUID g = {}; |
+ DWORD age = 0; |
+ DWORD dateStamp = 0; |
+ DWORD size = 0; |
+ |
+ // Settings for SymFindFileInPath |
+ void* id = nullptr; |
+ DWORD flags = 0; |
+ DWORD two = 0; |
+ |
+ const char* ext = strrchr(fileName, '.'); |
+ if (!ext) |
+ { |
+ printf("No extension found on %s. Fatal error.\n", fileName); |
+ return 0; |
+ } |
+ |
+ if (_stricmp(ext, ".pdb") == 0) |
+ { |
+ std::string gText; |
+ // Scan the GUID argument and remove all non-hex characters. This allows |
+ // passing GUIDs with '-', '{', and '}' characters. |
+ for (auto c : gTextArg) |
+ { |
+ if (isxdigit(c)) |
+ { |
+ gText.push_back(c); |
+ } |
+ } |
+ printf("Parsing symbol data for a PDB file.\n"); |
+ if (gText.size() != 32) |
+ { |
+ printf("Error: GUIDs must be exactly 32 characters" |
+ " (%s was stripped to %s).\n", gTextArg.c_str(), gText.c_str()); |
+ return 10; |
+ } |
+ |
+ int count = sscanf_s(gText.substr(0, 8).c_str(), "%x", &g.Data1); |
+ DWORD temp; |
+ count += sscanf_s(gText.substr(8, 4).c_str(), "%x", &temp); |
+ g.Data2 = (unsigned short)temp; |
+ count += sscanf_s(gText.substr(12, 4).c_str(), "%x", &temp); |
+ g.Data3 = (unsigned short)temp; |
+ for (auto i = 0; i < ARRAYSIZE(g.Data4); ++i) |
+ { |
+ count += sscanf_s(gText.substr(16 + i * 2, 2).c_str(), "%x", &temp); |
+ g.Data4[i] = (unsigned char)temp; |
+ } |
+ count += sscanf_s(ageText, "%x", &age); |
+ |
+ if (count != 12) |
+ { |
+ printf("Error: couldn't parse the GUID/age string. Sorry.\n"); |
+ return 10; |
+ } |
+ flags = SSRVOPT_GUIDPTR; |
+ id = &g; |
+ two = age; |
+ printf("Looking for %s %s %s.\n", gText.c_str(), ageText, fileName); |
+ } |
+ else |
+ { |
+ printf("Parsing symbol data for a PE (.dll or .exe) file.\n"); |
+ if (strlen(dateStampText) != 8) |
+ printf("Warning!!! The datestamp (%s) is not eight characters long. " |
+ "This is usually wrong.\n", dateStampText); |
+ int count = sscanf_s(dateStampText, "%x", &dateStamp); |
+ count += sscanf_s(sizeText, "%x", &size); |
+ flags = SSRVOPT_DWORDPTR; |
+ id = &dateStamp; |
+ two = size; |
+ printf("Looking for %s %x %x.\n", fileName, dateStamp, two); |
+ } |
+ |
+ char filePath[MAX_PATH] = {}; |
+ DWORD three = 0; |
+ |
+ if (SymFindFileInPath(fakeProcess, NULL, fileName, id, two, three, |
+ flags, filePath, NULL, NULL)) |
+ { |
+ printf("Found symbol file - placed it in %s.\n", filePath); |
+ } |
+ else |
+ { |
+ printf("Error: symbols not found - error %u. Are dbghelp.dll and " |
+ "symsrv.dll in the same directory as this executable?\n", |
+ GetLastError()); |
+ printf("Note that symbol server lookups sometimes fail randomly. " |
+ "Try again?\n"); |
+ } |
+ |
+ SymCleanup(fakeProcess); |
+ |
+ return 0; |
+} |