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" | |
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.
| |
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 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
| |
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; | |
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
| |
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 |