123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- // 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;
- }
|