Chromium Code Reviews| 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..2b8eb0de24b9c8d053d393d2a787abc9717e3f77 |
| --- /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" |
|
zturner
2015/02/24 23:53:07
Minor nit: any reason you chose to use quote synta
brucedawson
2015/02/25 00:15:21
Copy paste error I think. Fixed.
|
| +#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 gText = "072FF0EB54D24DFAAE9D13885486EE09"; |
|
zturner
2015/02/24 23:53:07
Is this supposed to be called gTextArg? Looks lik
brucedawson
2015/02/25 00:15:21
Good catch. I fixed that and verified that the TES
|
| + 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; |
|
zturner
2015/02/24 23:53:07
How about GUIDFromString()? Removes almost this e
brucedawson
2015/02/25 00:15:22
I looked at that function before and it seemed...
zturner
2015/02/25 00:29:33
Ahh yea, I didn't notice that. There's CLSIDFromS
|
| + // 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; |
| +} |