| 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;
|
| +}
|
|
|