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.
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/
14 // Link with the dbghelp import library
15 #pragma comment(lib, "dbghelp.lib")
17 // Uncomment this line to test with known-good parameters.
20 int main(int argc
, char* argv
[])
22 // Tell dbghelp to print diagnostics to the debugger output.
23 SymSetOptions(SYMOPT_DEBUG
);
26 const HANDLE fakeProcess
= (HANDLE
)1;
27 BOOL result
= SymInitialize(fakeProcess
, NULL
, FALSE
);
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");
36 // Valid PDB data to test the code.
37 std::string gTextArg
= "072FF0EB54D24DFAAE9D13885486EE09";
38 const char* ageText
= "2";
39 const char* fileName
= "kernel32.pdb";
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";
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]);
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];
67 // Parse the GUID and age from the text
73 // Settings for SymFindFileInPath
78 const char* ext
= strrchr(fileName
, '.');
81 printf("No extension found on %s. Fatal error.\n", fileName
);
85 if (_stricmp(ext
, ".pdb") == 0)
88 // Scan the GUID argument and remove all non-hex characters. This allows
89 // passing GUIDs with '-', '{', and '}' characters.
90 for (auto c
: gTextArg
)
97 printf("Parsing symbol data for a PDB file.\n");
98 if (gText
.size() != 32)
100 printf("Error: GUIDs must be exactly 32 characters"
101 " (%s was stripped to %s).\n", gTextArg
.c_str(), gText
.c_str());
105 int count
= sscanf_s(gText
.substr(0, 8).c_str(), "%x", &g
.Data1
);
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
)
113 count
+= sscanf_s(gText
.substr(16 + i
* 2, 2).c_str(), "%x", &temp
);
114 g
.Data4
[i
] = (unsigned char)temp
;
116 count
+= sscanf_s(ageText
, "%x", &age
);
120 printf("Error: couldn't parse the GUID/age string. Sorry.\n");
123 flags
= SSRVOPT_GUIDPTR
;
126 printf("Looking for %s %s %s.\n", gText
.c_str(), ageText
, fileName
);
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
;
139 printf("Looking for %s %x %x.\n", fileName
, dateStamp
, two
);
142 char filePath
[MAX_PATH
] = {};
145 if (SymFindFileInPath(fakeProcess
, NULL
, fileName
, id
, two
, three
,
146 flags
, filePath
, NULL
, NULL
))
148 printf("Found symbol file - placed it in %s.\n", filePath
);
152 printf("Error: symbols not found - error %u. Are dbghelp.dll and "
153 "symsrv.dll in the same directory as this executable?\n",
155 printf("Note that symbol server lookups sometimes fail randomly. "
159 SymCleanup(fakeProcess
);