1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <windows.h>
8 #include <dbghelp.h>
9 
10 const DWORD CV_SIGNATURE_RSDS = 0x53445352;  // 'SDSR'
11 
12 struct CV_INFO_PDB70 {
13   DWORD CvSignature;
14   GUID Signature;
15   DWORD Age;
16   BYTE PdbFileName[1];
17 };
18 
print_guid(const GUID & guid,DWORD age)19 void print_guid(const GUID& guid, DWORD age) {
20   printf("%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X", guid.Data1,
21          guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
22          guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6],
23          guid.Data4[7], age);
24 }
25 
main(int argc,char ** argv)26 int main(int argc, char** argv) {
27   if (argc != 2) {
28     fprintf(stderr, "usage: fileid <file>\n");
29     return 1;
30   }
31 
32   HANDLE file = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, nullptr,
33                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
34   if (file == INVALID_HANDLE_VALUE) {
35     fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
36     return 1;
37   }
38 
39   HANDLE mapFile = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, 0);
40   if (mapFile == nullptr) {
41     fprintf(stderr, "Couldn't create file mapping\n");
42     CloseHandle(file);
43     return 1;
44   }
45 
46   uint8_t* base = reinterpret_cast<uint8_t*>(
47       MapViewOfFile(mapFile, FILE_MAP_READ, 0, 0, 0));
48   if (base == nullptr) {
49     fprintf(stderr, "Couldn't map file\n");
50     CloseHandle(mapFile);
51     CloseHandle(file);
52     return 1;
53   }
54 
55   DWORD size;
56   PIMAGE_DEBUG_DIRECTORY debug_dir =
57       reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(ImageDirectoryEntryToDataEx(
58           base, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &size, nullptr));
59 
60   bool found = false;
61   if (debug_dir->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
62     CV_INFO_PDB70* cv =
63         reinterpret_cast<CV_INFO_PDB70*>(base + debug_dir->PointerToRawData);
64     if (cv->CvSignature == CV_SIGNATURE_RSDS) {
65       found = true;
66       print_guid(cv->Signature, cv->Age);
67     }
68   }
69 
70   UnmapViewOfFile(base);
71   CloseHandle(mapFile);
72   CloseHandle(file);
73 
74   return found ? 0 : 1;
75 }
76