OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Symbol downloading demonstration code. |
| 6 // For more information see ReadMe.txt and this blog post: |
| 7 // https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/ |
| 8 |
| 9 #include <stdio.h> |
| 10 #include <Windows.h> |
| 11 #include <DbgHelp.h> |
| 12 #include <string> |
| 13 |
| 14 // Link with the dbghelp import library |
| 15 #pragma comment(lib, "dbghelp.lib") |
| 16 |
| 17 // Uncomment this line to test with known-good parameters. |
| 18 //#define TESTING |
| 19 |
| 20 int main(int argc, char* argv[]) |
| 21 { |
| 22 // Tell dbghelp to print diagnostics to the debugger output. |
| 23 SymSetOptions(SYMOPT_DEBUG); |
| 24 |
| 25 // Initialize dbghelp |
| 26 const HANDLE fakeProcess = (HANDLE)1; |
| 27 BOOL result = SymInitialize(fakeProcess, NULL, FALSE); |
| 28 |
| 29 #ifdef TESTING |
| 30 // Set a search path and cache directory. If this isn't set |
| 31 // then _NT_SYMBOL_PATH will be used instead. |
| 32 // Force setting it here to make sure that the test succeeds. |
| 33 SymSetSearchPath(fakeProcess, |
| 34 "SRV*c:\\symbolstest*http://msdl.microsoft.com/download/symbols"); |
| 35 |
| 36 // Valid PDB data to test the code. |
| 37 std::string gTextArg = "072FF0EB54D24DFAAE9D13885486EE09"; |
| 38 const char* ageText = "2"; |
| 39 const char* fileName = "kernel32.pdb"; |
| 40 |
| 41 // Valid PE data to test the code |
| 42 fileName = "crypt32.dll"; |
| 43 const char* dateStampText = "4802A0D7"; |
| 44 const char* sizeText = "95000"; |
| 45 //fileName = "chrome_child.dll"; |
| 46 //const char* dateStampText = "5420D824"; |
| 47 //const char* sizeText = "20a6000"; |
| 48 #else |
| 49 if (argc < 4) |
| 50 { |
| 51 printf("Error: insufficient arguments.\n"); |
| 52 printf("Usage: %s guid age pdbname\n", argv[0]); |
| 53 printf("Usage: %s dateStamp size pename\n", argv[0]); |
| 54 printf("Example: %s 6720c31f4ac24f3ab0243e0641a4412f 1 " |
| 55 "chrome_child.dll.pdb\n", argv[0]); |
| 56 printf("Example: %s 4802A0D7 95000 crypt32.dll\n", argv[0]); |
| 57 return 0; |
| 58 } |
| 59 |
| 60 std::string gTextArg = argv[1]; |
| 61 const char* dateStampText = argv[1]; |
| 62 const char* ageText = argv[2]; |
| 63 const char* sizeText = argv[2]; |
| 64 const char* fileName = argv[3]; |
| 65 #endif |
| 66 |
| 67 // Parse the GUID and age from the text |
| 68 GUID g = {}; |
| 69 DWORD age = 0; |
| 70 DWORD dateStamp = 0; |
| 71 DWORD size = 0; |
| 72 |
| 73 // Settings for SymFindFileInPath |
| 74 void* id = nullptr; |
| 75 DWORD flags = 0; |
| 76 DWORD two = 0; |
| 77 |
| 78 const char* ext = strrchr(fileName, '.'); |
| 79 if (!ext) |
| 80 { |
| 81 printf("No extension found on %s. Fatal error.\n", fileName); |
| 82 return 0; |
| 83 } |
| 84 |
| 85 if (_stricmp(ext, ".pdb") == 0) |
| 86 { |
| 87 std::string gText; |
| 88 // Scan the GUID argument and remove all non-hex characters. This allows |
| 89 // passing GUIDs with '-', '{', and '}' characters. |
| 90 for (auto c : gTextArg) |
| 91 { |
| 92 if (isxdigit(c)) |
| 93 { |
| 94 gText.push_back(c); |
| 95 } |
| 96 } |
| 97 printf("Parsing symbol data for a PDB file.\n"); |
| 98 if (gText.size() != 32) |
| 99 { |
| 100 printf("Error: GUIDs must be exactly 32 characters" |
| 101 " (%s was stripped to %s).\n", gTextArg.c_str(), gText.c_str()); |
| 102 return 10; |
| 103 } |
| 104 |
| 105 int count = sscanf_s(gText.substr(0, 8).c_str(), "%x", &g.Data1); |
| 106 DWORD temp; |
| 107 count += sscanf_s(gText.substr(8, 4).c_str(), "%x", &temp); |
| 108 g.Data2 = (unsigned short)temp; |
| 109 count += sscanf_s(gText.substr(12, 4).c_str(), "%x", &temp); |
| 110 g.Data3 = (unsigned short)temp; |
| 111 for (auto i = 0; i < ARRAYSIZE(g.Data4); ++i) |
| 112 { |
| 113 count += sscanf_s(gText.substr(16 + i * 2, 2).c_str(), "%x", &temp); |
| 114 g.Data4[i] = (unsigned char)temp; |
| 115 } |
| 116 count += sscanf_s(ageText, "%x", &age); |
| 117 |
| 118 if (count != 12) |
| 119 { |
| 120 printf("Error: couldn't parse the GUID/age string. Sorry.\n"); |
| 121 return 10; |
| 122 } |
| 123 flags = SSRVOPT_GUIDPTR; |
| 124 id = &g; |
| 125 two = age; |
| 126 printf("Looking for %s %s %s.\n", gText.c_str(), ageText, fileName); |
| 127 } |
| 128 else |
| 129 { |
| 130 printf("Parsing symbol data for a PE (.dll or .exe) file.\n"); |
| 131 if (strlen(dateStampText) != 8) |
| 132 printf("Warning!!! The datestamp (%s) is not eight characters long. " |
| 133 "This is usually wrong.\n", dateStampText); |
| 134 int count = sscanf_s(dateStampText, "%x", &dateStamp); |
| 135 count += sscanf_s(sizeText, "%x", &size); |
| 136 flags = SSRVOPT_DWORDPTR; |
| 137 id = &dateStamp; |
| 138 two = size; |
| 139 printf("Looking for %s %x %x.\n", fileName, dateStamp, two); |
| 140 } |
| 141 |
| 142 char filePath[MAX_PATH] = {}; |
| 143 DWORD three = 0; |
| 144 |
| 145 if (SymFindFileInPath(fakeProcess, NULL, fileName, id, two, three, |
| 146 flags, filePath, NULL, NULL)) |
| 147 { |
| 148 printf("Found symbol file - placed it in %s.\n", filePath); |
| 149 } |
| 150 else |
| 151 { |
| 152 printf("Error: symbols not found - error %u. Are dbghelp.dll and " |
| 153 "symsrv.dll in the same directory as this executable?\n", |
| 154 GetLastError()); |
| 155 printf("Note that symbol server lookups sometimes fail randomly. " |
| 156 "Try again?\n"); |
| 157 } |
| 158 |
| 159 SymCleanup(fakeProcess); |
| 160 |
| 161 return 0; |
| 162 } |
OLD | NEW |