1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "common/windows/pdb_source_line_writer.h"
31 
32 #include <windows.h>
33 #include <winnt.h>
34 #include <atlbase.h>
35 #include <dia2.h>
36 #include <diacreate.h>
37 #include <ImageHlp.h>
38 #include <stdio.h>
39 
40 #include <limits>
41 #include <set>
42 
43 #include "common/windows/dia_util.h"
44 #include "common/windows/guid_string.h"
45 #include "common/windows/string_utils-inl.h"
46 
47 // This constant may be missing from DbgHelp.h.  See the documentation for
48 // IDiaSymbol::get_undecoratedNameEx.
49 #ifndef UNDNAME_NO_ECSU
50 #define UNDNAME_NO_ECSU 0x8000  // Suppresses enum/class/struct/union.
51 #endif  // UNDNAME_NO_ECSU
52 
53 /*
54  * Not defined in WinNT.h for some reason. Definitions taken from:
55  * http://uninformed.org/index.cgi?v=4&a=1&p=13
56  *
57  */
58 typedef unsigned char UBYTE;
59 
60 #if !defined(_WIN64)
61 #define UNW_FLAG_EHANDLER  0x01
62 #define UNW_FLAG_UHANDLER  0x02
63 #define UNW_FLAG_CHAININFO 0x04
64 #endif
65 
66 union UnwindCode {
67   struct {
68     UBYTE offset_in_prolog;
69     UBYTE unwind_operation_code : 4;
70     UBYTE operation_info        : 4;
71   };
72   USHORT frame_offset;
73 };
74 
75 enum UnwindOperationCodes {
76   UWOP_PUSH_NONVOL = 0, /* info == register number */
77   UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */
78   UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */
79   UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
80   UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */
81   UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
82   // XXX: these are missing from MSDN!
83   // See: http://www.osronline.com/ddkx/kmarch/64bitamd_4rs7.htm
84   UWOP_SAVE_XMM,
85   UWOP_SAVE_XMM_FAR,
86   UWOP_SAVE_XMM128,     /* info == XMM reg number, offset in next slot */
87   UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
88   UWOP_PUSH_MACHFRAME   /* info == 0: no error-code, 1: error-code */
89 };
90 
91 // See: http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
92 // Note: some fields removed as we don't use them.
93 struct UnwindInfo {
94   UBYTE version       : 3;
95   UBYTE flags         : 5;
96   UBYTE size_of_prolog;
97   UBYTE count_of_codes;
98   UBYTE frame_register : 4;
99   UBYTE frame_offset   : 4;
100   UnwindCode unwind_code[1];
101 };
102 
103 namespace google_breakpad {
104 
105 namespace {
106 
107 using std::vector;
108 
109 // A helper class to scope a PLOADED_IMAGE.
110 class AutoImage {
111  public:
AutoImage(PLOADED_IMAGE img)112   explicit AutoImage(PLOADED_IMAGE img) : img_(img) {}
~AutoImage()113   ~AutoImage() {
114     if (img_)
115       ImageUnload(img_);
116   }
117 
operator PLOADED_IMAGE()118   operator PLOADED_IMAGE() { return img_; }
operator ->()119   PLOADED_IMAGE operator->() { return img_; }
120 
121  private:
122   PLOADED_IMAGE img_;
123 };
124 
CreateDiaDataSourceInstance(CComPtr<IDiaDataSource> & data_source)125 bool CreateDiaDataSourceInstance(CComPtr<IDiaDataSource> &data_source) {
126   if (SUCCEEDED(data_source.CoCreateInstance(CLSID_DiaSource))) {
127     return true;
128   }
129 
130   class DECLSPEC_UUID("B86AE24D-BF2F-4ac9-B5A2-34B14E4CE11D") DiaSource100;
131   class DECLSPEC_UUID("761D3BCD-1304-41D5-94E8-EAC54E4AC172") DiaSource110;
132   class DECLSPEC_UUID("3BFCEA48-620F-4B6B-81F7-B9AF75454C7D") DiaSource120;
133   class DECLSPEC_UUID("E6756135-1E65-4D17-8576-610761398C3C") DiaSource140;
134 
135   // If the CoCreateInstance call above failed, msdia*.dll is not registered.
136   // We can try loading the DLL corresponding to the #included DIA SDK, but
137   // the DIA headers don't provide a version. Lets try to figure out which DIA
138   // version we're compiling against by comparing CLSIDs.
139   const wchar_t *msdia_dll = nullptr;
140   if (CLSID_DiaSource == _uuidof(DiaSource100)) {
141     msdia_dll = L"msdia100.dll";
142   } else if (CLSID_DiaSource == _uuidof(DiaSource110)) {
143     msdia_dll = L"msdia110.dll";
144   } else if (CLSID_DiaSource == _uuidof(DiaSource120)) {
145     msdia_dll = L"msdia120.dll";
146   } else if (CLSID_DiaSource == _uuidof(DiaSource140)) {
147     msdia_dll = L"msdia140.dll";
148   }
149 
150   if (msdia_dll &&
151       SUCCEEDED(NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
152                               reinterpret_cast<void **>(&data_source)))) {
153     return true;
154   }
155 
156   return false;
157 }
158 
159 }  // namespace
160 
PDBSourceLineWriter()161 PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) {
162 }
163 
~PDBSourceLineWriter()164 PDBSourceLineWriter::~PDBSourceLineWriter() {
165 }
166 
SetCodeFile(const wstring & exe_file)167 bool PDBSourceLineWriter::SetCodeFile(const wstring &exe_file) {
168   if (code_file_.empty()) {
169     code_file_ = exe_file;
170     return true;
171   }
172   // Setting a different code file path is an error.  It is success only if the
173   // file paths are the same.
174   return exe_file == code_file_;
175 }
176 
Open(const wstring & file,FileFormat format)177 bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) {
178   Close();
179   code_file_.clear();
180 
181   if (FAILED(CoInitialize(NULL))) {
182     fprintf(stderr, "CoInitialize failed\n");
183     return false;
184   }
185 
186   CComPtr<IDiaDataSource> data_source;
187   if (!CreateDiaDataSourceInstance(data_source)) {
188     const int kGuidSize = 64;
189     wchar_t classid[kGuidSize] = {0};
190     StringFromGUID2(CLSID_DiaSource, classid, kGuidSize);
191     fprintf(stderr, "CoCreateInstance CLSID_DiaSource %S failed "
192             "(msdia*.dll unregistered?)\n", classid);
193     return false;
194   }
195 
196   switch (format) {
197     case PDB_FILE:
198       if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
199         fprintf(stderr, "loadDataFromPdb failed for %ws\n", file.c_str());
200         return false;
201       }
202       break;
203     case EXE_FILE:
204       if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
205         fprintf(stderr, "loadDataForExe failed for %ws\n", file.c_str());
206         return false;
207       }
208       code_file_ = file;
209       break;
210     case ANY_FILE:
211       if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
212         if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
213           fprintf(stderr, "loadDataForPdb and loadDataFromExe failed for %ws\n",
214                   file.c_str());
215           return false;
216         }
217         code_file_ = file;
218       }
219       break;
220     default:
221       fprintf(stderr, "Unknown file format\n");
222       return false;
223   }
224 
225   if (FAILED(data_source->openSession(&session_))) {
226     fprintf(stderr, "openSession failed\n");
227   }
228 
229   return true;
230 }
231 
PrintLines(IDiaEnumLineNumbers * lines)232 bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) {
233   // The line number format is:
234   // <rva> <line number> <source file id>
235   CComPtr<IDiaLineNumber> line;
236   ULONG count;
237 
238   while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) {
239     DWORD rva;
240     if (FAILED(line->get_relativeVirtualAddress(&rva))) {
241       fprintf(stderr, "failed to get line rva\n");
242       return false;
243     }
244 
245     DWORD length;
246     if (FAILED(line->get_length(&length))) {
247       fprintf(stderr, "failed to get line code length\n");
248       return false;
249     }
250 
251     DWORD dia_source_id;
252     if (FAILED(line->get_sourceFileId(&dia_source_id))) {
253       fprintf(stderr, "failed to get line source file id\n");
254       return false;
255     }
256     // duplicate file names are coalesced to share one ID
257     DWORD source_id = GetRealFileID(dia_source_id);
258 
259     DWORD line_num;
260     if (FAILED(line->get_lineNumber(&line_num))) {
261       fprintf(stderr, "failed to get line number\n");
262       return false;
263     }
264 
265     AddressRangeVector ranges;
266     MapAddressRange(image_map_, AddressRange(rva, length), &ranges);
267     for (size_t i = 0; i < ranges.size(); ++i) {
268       fprintf(output_, "%x %x %d %d\n", ranges[i].rva, ranges[i].length,
269               line_num, source_id);
270     }
271     line.Release();
272   }
273   return true;
274 }
275 
PrintFunction(IDiaSymbol * function,IDiaSymbol * block)276 bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
277                                         IDiaSymbol *block) {
278   // The function format is:
279   // FUNC <address> <length> <param_stack_size> <function>
280   DWORD rva;
281   if (FAILED(block->get_relativeVirtualAddress(&rva))) {
282     fprintf(stderr, "couldn't get rva\n");
283     return false;
284   }
285 
286   ULONGLONG length;
287   if (FAILED(block->get_length(&length))) {
288     fprintf(stderr, "failed to get function length\n");
289     return false;
290   }
291 
292   if (length == 0) {
293     // Silently ignore zero-length functions, which can infrequently pop up.
294     return true;
295   }
296 
297   CComBSTR name;
298   int stack_param_size;
299   if (!GetSymbolFunctionName(function, &name, &stack_param_size)) {
300     return false;
301   }
302 
303   // If the decorated name didn't give the parameter size, try to
304   // calculate it.
305   if (stack_param_size < 0) {
306     stack_param_size = GetFunctionStackParamSize(function);
307   }
308 
309   AddressRangeVector ranges;
310   MapAddressRange(image_map_, AddressRange(rva, static_cast<DWORD>(length)),
311                   &ranges);
312   for (size_t i = 0; i < ranges.size(); ++i) {
313     fprintf(output_, "FUNC %x %x %x %ws\n",
314             ranges[i].rva, ranges[i].length, stack_param_size,
315             name.m_str);
316   }
317 
318   CComPtr<IDiaEnumLineNumbers> lines;
319   if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) {
320     return false;
321   }
322 
323   if (!PrintLines(lines)) {
324     return false;
325   }
326   return true;
327 }
328 
PrintSourceFiles()329 bool PDBSourceLineWriter::PrintSourceFiles() {
330   CComPtr<IDiaSymbol> global;
331   if (FAILED(session_->get_globalScope(&global))) {
332     fprintf(stderr, "get_globalScope failed\n");
333     return false;
334   }
335 
336   CComPtr<IDiaEnumSymbols> compilands;
337   if (FAILED(global->findChildren(SymTagCompiland, NULL,
338                                   nsNone, &compilands))) {
339     fprintf(stderr, "findChildren failed\n");
340     return false;
341   }
342 
343   CComPtr<IDiaSymbol> compiland;
344   ULONG count;
345   while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
346     CComPtr<IDiaEnumSourceFiles> source_files;
347     if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) {
348       return false;
349     }
350     CComPtr<IDiaSourceFile> file;
351     while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) {
352       DWORD file_id;
353       if (FAILED(file->get_uniqueId(&file_id))) {
354         return false;
355       }
356 
357       CComBSTR file_name;
358       if (FAILED(file->get_fileName(&file_name))) {
359         return false;
360       }
361 
362       wstring file_name_string(file_name);
363       if (!FileIDIsCached(file_name_string)) {
364         // this is a new file name, cache it and output a FILE line.
365         CacheFileID(file_name_string, file_id);
366         fwprintf(output_, L"FILE %d %ws\n", file_id, file_name_string.c_str());
367       } else {
368         // this file name has already been seen, just save this
369         // ID for later lookup.
370         StoreDuplicateFileID(file_name_string, file_id);
371       }
372       file.Release();
373     }
374     compiland.Release();
375   }
376   return true;
377 }
378 
PrintFunctions()379 bool PDBSourceLineWriter::PrintFunctions() {
380   ULONG count = 0;
381   DWORD rva = 0;
382   CComPtr<IDiaSymbol> global;
383   HRESULT hr;
384 
385   if (FAILED(session_->get_globalScope(&global))) {
386     fprintf(stderr, "get_globalScope failed\n");
387     return false;
388   }
389 
390   CComPtr<IDiaEnumSymbols> symbols = NULL;
391 
392   // Find all function symbols first.
393   std::set<DWORD> rvas;
394   hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols);
395 
396   if (SUCCEEDED(hr)) {
397     CComPtr<IDiaSymbol> symbol = NULL;
398 
399     while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
400       if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
401         // To maintain existing behavior of one symbol per address, place the
402         // rva onto a set here to uniquify them.
403         rvas.insert(rva);
404       } else {
405         fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
406         return false;
407       }
408 
409       symbol.Release();
410     }
411 
412     symbols.Release();
413   }
414 
415   // Find all public symbols.  Store public symbols that are not also private
416   // symbols for later.
417   std::set<DWORD> public_only_rvas;
418   hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols);
419 
420   if (SUCCEEDED(hr)) {
421     CComPtr<IDiaSymbol> symbol = NULL;
422 
423     while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
424       if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
425         if (rvas.count(rva) == 0) {
426           rvas.insert(rva); // Keep symbols in rva order.
427           public_only_rvas.insert(rva);
428         }
429       } else {
430         fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
431         return false;
432       }
433 
434       symbol.Release();
435     }
436 
437     symbols.Release();
438   }
439 
440   std::set<DWORD>::iterator it;
441 
442   // For each rva, dump the first symbol DIA knows about at the address.
443   for (it = rvas.begin(); it != rvas.end(); ++it) {
444     CComPtr<IDiaSymbol> symbol = NULL;
445     // If the symbol is not in the public list, look for SymTagFunction. This is
446     // a workaround to a bug where DIA will hang if searching for a private
447     // symbol at an address where only a public symbol exists.
448     // See http://connect.microsoft.com/VisualStudio/feedback/details/722366
449     if (public_only_rvas.count(*it) == 0) {
450       if (SUCCEEDED(session_->findSymbolByRVA(*it, SymTagFunction, &symbol))) {
451         // Sometimes findSymbolByRVA returns S_OK, but NULL.
452         if (symbol) {
453           if (!PrintFunction(symbol, symbol))
454             return false;
455           symbol.Release();
456         }
457       } else {
458         fprintf(stderr, "findSymbolByRVA SymTagFunction failed\n");
459         return false;
460       }
461     } else if (SUCCEEDED(session_->findSymbolByRVA(*it,
462                                                    SymTagPublicSymbol,
463                                                    &symbol))) {
464       // Sometimes findSymbolByRVA returns S_OK, but NULL.
465       if (symbol) {
466         if (!PrintCodePublicSymbol(symbol))
467           return false;
468         symbol.Release();
469       }
470     } else {
471       fprintf(stderr, "findSymbolByRVA SymTagPublicSymbol failed\n");
472       return false;
473     }
474   }
475 
476   // When building with PGO, the compiler can split functions into
477   // "hot" and "cold" blocks, and move the "cold" blocks out to separate
478   // pages, so the function can be noncontiguous. To find these blocks,
479   // we have to iterate over all the compilands, and then find blocks
480   // that are children of them. We can then find the lexical parents
481   // of those blocks and print out an extra FUNC line for blocks
482   // that are not contained in their parent functions.
483   CComPtr<IDiaEnumSymbols> compilands;
484   if (FAILED(global->findChildren(SymTagCompiland, NULL,
485                                   nsNone, &compilands))) {
486     fprintf(stderr, "findChildren failed on the global\n");
487     return false;
488   }
489 
490   CComPtr<IDiaSymbol> compiland;
491   while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
492     CComPtr<IDiaEnumSymbols> blocks;
493     if (FAILED(compiland->findChildren(SymTagBlock, NULL,
494                                        nsNone, &blocks))) {
495       fprintf(stderr, "findChildren failed on a compiland\n");
496       return false;
497     }
498 
499     CComPtr<IDiaSymbol> block;
500     while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) {
501       // find this block's lexical parent function
502       CComPtr<IDiaSymbol> parent;
503       DWORD tag;
504       if (SUCCEEDED(block->get_lexicalParent(&parent)) &&
505           SUCCEEDED(parent->get_symTag(&tag)) &&
506           tag == SymTagFunction) {
507         // now get the block's offset and the function's offset and size,
508         // and determine if the block is outside of the function
509         DWORD func_rva, block_rva;
510         ULONGLONG func_length;
511         if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) &&
512             SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) &&
513             SUCCEEDED(parent->get_length(&func_length))) {
514           if (block_rva < func_rva || block_rva > (func_rva + func_length)) {
515             if (!PrintFunction(parent, block)) {
516               return false;
517             }
518           }
519         }
520       }
521       parent.Release();
522       block.Release();
523     }
524     blocks.Release();
525     compiland.Release();
526   }
527 
528   global.Release();
529   return true;
530 }
531 
532 #undef max
533 
PrintFrameDataUsingPDB()534 bool PDBSourceLineWriter::PrintFrameDataUsingPDB() {
535   // It would be nice if it were possible to output frame data alongside the
536   // associated function, as is done with line numbers, but the DIA API
537   // doesn't make it possible to get the frame data in that way.
538 
539   CComPtr<IDiaEnumFrameData> frame_data_enum;
540   if (!FindTable(session_, &frame_data_enum))
541     return false;
542 
543   DWORD last_type = std::numeric_limits<DWORD>::max();
544   DWORD last_rva = std::numeric_limits<DWORD>::max();
545   DWORD last_code_size = 0;
546   DWORD last_prolog_size = std::numeric_limits<DWORD>::max();
547 
548   CComPtr<IDiaFrameData> frame_data;
549   ULONG count = 0;
550   while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) &&
551          count == 1) {
552     DWORD type;
553     if (FAILED(frame_data->get_type(&type)))
554       return false;
555 
556     DWORD rva;
557     if (FAILED(frame_data->get_relativeVirtualAddress(&rva)))
558       return false;
559 
560     DWORD code_size;
561     if (FAILED(frame_data->get_lengthBlock(&code_size)))
562       return false;
563 
564     DWORD prolog_size;
565     if (FAILED(frame_data->get_lengthProlog(&prolog_size)))
566       return false;
567 
568     // parameter_size is the size of parameters passed on the stack.  If any
569     // parameters are not passed on the stack (such as in registers), their
570     // sizes will not be included in parameter_size.
571     DWORD parameter_size;
572     if (FAILED(frame_data->get_lengthParams(&parameter_size)))
573       return false;
574 
575     DWORD saved_register_size;
576     if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size)))
577       return false;
578 
579     DWORD local_size;
580     if (FAILED(frame_data->get_lengthLocals(&local_size)))
581       return false;
582 
583     // get_maxStack can return S_FALSE, just use 0 in that case.
584     DWORD max_stack_size = 0;
585     if (FAILED(frame_data->get_maxStack(&max_stack_size)))
586       return false;
587 
588     // get_programString can return S_FALSE, indicating that there is no
589     // program string.  In that case, check whether %ebp is used.
590     HRESULT program_string_result;
591     CComBSTR program_string;
592     if (FAILED(program_string_result = frame_data->get_program(
593         &program_string))) {
594       return false;
595     }
596 
597     // get_allocatesBasePointer can return S_FALSE, treat that as though
598     // %ebp is not used.
599     BOOL allocates_base_pointer = FALSE;
600     if (program_string_result != S_OK) {
601       if (FAILED(frame_data->get_allocatesBasePointer(
602           &allocates_base_pointer))) {
603         return false;
604       }
605     }
606 
607     // Only print out a line if type, rva, code_size, or prolog_size have
608     // changed from the last line.  It is surprisingly common (especially in
609     // system library PDBs) for DIA to return a series of identical
610     // IDiaFrameData objects.  For kernel32.pdb from Windows XP SP2 on x86,
611     // this check reduces the size of the dumped symbol file by a third.
612     if (type != last_type || rva != last_rva || code_size != last_code_size ||
613         prolog_size != last_prolog_size) {
614       // The prolog and the code portions of the frame have to be treated
615       // independently as they may have independently changed in size, or may
616       // even have been split.
617       // NOTE: If epilog size is ever non-zero, we have to do something
618       //     similar with it.
619 
620       // Figure out where the prolog bytes have landed.
621       AddressRangeVector prolog_ranges;
622       if (prolog_size > 0) {
623         MapAddressRange(image_map_, AddressRange(rva, prolog_size),
624                         &prolog_ranges);
625       }
626 
627       // And figure out where the code bytes have landed.
628       AddressRangeVector code_ranges;
629       MapAddressRange(image_map_,
630                       AddressRange(rva + prolog_size,
631                                    code_size - prolog_size),
632                       &code_ranges);
633 
634       struct FrameInfo {
635         DWORD rva;
636         DWORD code_size;
637         DWORD prolog_size;
638       };
639       std::vector<FrameInfo> frame_infos;
640 
641       // Special case: The prolog and the code bytes remain contiguous. This is
642       // only done for compactness of the symbol file, and we could actually
643       // be outputting independent frame info for the prolog and code portions.
644       if (prolog_ranges.size() == 1 && code_ranges.size() == 1 &&
645           prolog_ranges[0].end() == code_ranges[0].rva) {
646         FrameInfo fi = { prolog_ranges[0].rva,
647                          prolog_ranges[0].length + code_ranges[0].length,
648                          prolog_ranges[0].length };
649         frame_infos.push_back(fi);
650       } else {
651         // Otherwise we output the prolog and code frame info independently.
652         for (size_t i = 0; i < prolog_ranges.size(); ++i) {
653           FrameInfo fi = { prolog_ranges[i].rva,
654                            prolog_ranges[i].length,
655                            prolog_ranges[i].length };
656           frame_infos.push_back(fi);
657         }
658         for (size_t i = 0; i < code_ranges.size(); ++i) {
659           FrameInfo fi = { code_ranges[i].rva, code_ranges[i].length, 0 };
660           frame_infos.push_back(fi);
661         }
662       }
663 
664       for (size_t i = 0; i < frame_infos.size(); ++i) {
665         const FrameInfo& fi(frame_infos[i]);
666         fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ",
667                 type, fi.rva, fi.code_size, fi.prolog_size,
668                 0 /* epilog_size */, parameter_size, saved_register_size,
669                 local_size, max_stack_size, program_string_result == S_OK);
670         if (program_string_result == S_OK) {
671           fprintf(output_, "%ws\n", program_string.m_str);
672         } else {
673           fprintf(output_, "%d\n", allocates_base_pointer);
674         }
675       }
676 
677       last_type = type;
678       last_rva = rva;
679       last_code_size = code_size;
680       last_prolog_size = prolog_size;
681     }
682 
683     frame_data.Release();
684   }
685 
686   return true;
687 }
688 
PrintFrameDataUsingEXE()689 bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
690   if (code_file_.empty() && !FindPEFile()) {
691     fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
692     return false;
693   }
694 
695   // Convert wchar to native charset because ImageLoad only takes
696   // a PSTR as input.
697   string code_file;
698   if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
699     return false;
700   }
701 
702   AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
703   if (!img) {
704     fprintf(stderr, "Failed to load %s\n", code_file.c_str());
705     return false;
706   }
707   PIMAGE_OPTIONAL_HEADER64 optional_header =
708     &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
709   if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
710     fprintf(stderr, "Not a PE32+ image\n");
711     return false;
712   }
713 
714   // Read Exception Directory
715   DWORD exception_rva = optional_header->
716     DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
717   DWORD exception_size = optional_header->
718     DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
719   PIMAGE_RUNTIME_FUNCTION_ENTRY funcs =
720     static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
721         ImageRvaToVa(img->FileHeader,
722                      img->MappedAddress,
723                      exception_rva,
724                      &img->LastRvaSection));
725   for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
726     DWORD unwind_rva = funcs[i].UnwindInfoAddress;
727     // handle chaining
728     while (unwind_rva & 0x1) {
729       unwind_rva ^= 0x1;
730       PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
731         static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
732             ImageRvaToVa(img->FileHeader,
733                          img->MappedAddress,
734                          unwind_rva,
735                          &img->LastRvaSection));
736       unwind_rva = chained_func->UnwindInfoAddress;
737     }
738 
739     UnwindInfo *unwind_info = static_cast<UnwindInfo *>(
740         ImageRvaToVa(img->FileHeader,
741                      img->MappedAddress,
742                      unwind_rva,
743                      &img->LastRvaSection));
744 
745     DWORD stack_size = 8;  // minimal stack size is 8 for RIP
746     DWORD rip_offset = 8;
747     do {
748       for (UBYTE c = 0; c < unwind_info->count_of_codes; c++) {
749         UnwindCode *unwind_code = &unwind_info->unwind_code[c];
750         switch (unwind_code->unwind_operation_code) {
751           case UWOP_PUSH_NONVOL: {
752             stack_size += 8;
753             break;
754           }
755           case UWOP_ALLOC_LARGE: {
756             if (unwind_code->operation_info == 0) {
757               c++;
758               if (c < unwind_info->count_of_codes)
759                 stack_size += (unwind_code + 1)->frame_offset * 8;
760             } else {
761               c += 2;
762               if (c < unwind_info->count_of_codes)
763                 stack_size += (unwind_code + 1)->frame_offset |
764                               ((unwind_code + 2)->frame_offset << 16);
765             }
766             break;
767           }
768           case UWOP_ALLOC_SMALL: {
769             stack_size += unwind_code->operation_info * 8 + 8;
770             break;
771           }
772           case UWOP_SET_FPREG:
773           case UWOP_SAVE_XMM:
774           case UWOP_SAVE_XMM_FAR:
775             break;
776           case UWOP_SAVE_NONVOL:
777           case UWOP_SAVE_XMM128: {
778             c++;  // skip slot with offset
779             break;
780           }
781           case UWOP_SAVE_NONVOL_FAR:
782           case UWOP_SAVE_XMM128_FAR: {
783             c += 2;  // skip 2 slots with offset
784             break;
785           }
786           case UWOP_PUSH_MACHFRAME: {
787             if (unwind_code->operation_info) {
788               stack_size += 88;
789             } else {
790               stack_size += 80;
791             }
792             rip_offset += 80;
793             break;
794           }
795         }
796       }
797       if (unwind_info->flags & UNW_FLAG_CHAININFO) {
798         PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
799           reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
800               (unwind_info->unwind_code +
801               ((unwind_info->count_of_codes + 1) & ~1)));
802 
803         unwind_info = static_cast<UnwindInfo *>(
804             ImageRvaToVa(img->FileHeader,
805                          img->MappedAddress,
806                          chained_func->UnwindInfoAddress,
807                          &img->LastRvaSection));
808       } else {
809         unwind_info = NULL;
810       }
811     } while (unwind_info);
812     fprintf(output_, "STACK CFI INIT %x %x .cfa: $rsp .ra: .cfa %d - ^\n",
813             funcs[i].BeginAddress,
814             funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
815     fprintf(output_, "STACK CFI %x .cfa: $rsp %d +\n",
816             funcs[i].BeginAddress, stack_size);
817   }
818 
819   return true;
820 }
821 
PrintFrameData()822 bool PDBSourceLineWriter::PrintFrameData() {
823   PDBModuleInfo info;
824   if (GetModuleInfo(&info) && info.cpu == L"x86_64") {
825     return PrintFrameDataUsingEXE();
826   } else {
827     return PrintFrameDataUsingPDB();
828   }
829   return false;
830 }
831 
PrintCodePublicSymbol(IDiaSymbol * symbol)832 bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) {
833   BOOL is_code;
834   if (FAILED(symbol->get_code(&is_code))) {
835     return false;
836   }
837   if (!is_code) {
838     return true;
839   }
840 
841   DWORD rva;
842   if (FAILED(symbol->get_relativeVirtualAddress(&rva))) {
843     return false;
844   }
845 
846   CComBSTR name;
847   int stack_param_size;
848   if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) {
849     return false;
850   }
851 
852   AddressRangeVector ranges;
853   MapAddressRange(image_map_, AddressRange(rva, 1), &ranges);
854   for (size_t i = 0; i < ranges.size(); ++i) {
855     fprintf(output_, "PUBLIC %x %x %ws\n", ranges[i].rva,
856             stack_param_size > 0 ? stack_param_size : 0,
857             name.m_str);
858   }
859   return true;
860 }
861 
PrintPDBInfo()862 bool PDBSourceLineWriter::PrintPDBInfo() {
863   PDBModuleInfo info;
864   if (!GetModuleInfo(&info)) {
865     return false;
866   }
867 
868   // Hard-code "windows" for the OS because that's the only thing that makes
869   // sense for PDB files.  (This might not be strictly correct for Windows CE
870   // support, but we don't care about that at the moment.)
871   fprintf(output_, "MODULE windows %ws %ws %ws\n",
872           info.cpu.c_str(), info.debug_identifier.c_str(),
873           info.debug_file.c_str());
874 
875   return true;
876 }
877 
PrintPEInfo()878 bool PDBSourceLineWriter::PrintPEInfo() {
879   PEModuleInfo info;
880   if (!GetPEInfo(&info)) {
881     return false;
882   }
883 
884   fprintf(output_, "INFO CODE_ID %ws %ws\n",
885           info.code_identifier.c_str(),
886           info.code_file.c_str());
887   return true;
888 }
889 
890 // wcstol_positive_strict is sort of like wcstol, but much stricter.  string
891 // should be a buffer pointing to a null-terminated string containing only
892 // decimal digits.  If the entire string can be converted to an integer
893 // without overflowing, and there are no non-digit characters before the
894 // result is set to the value and this function returns true.  Otherwise,
895 // this function returns false.  This is an alternative to the strtol, atoi,
896 // and scanf families, which are not as strict about input and in some cases
897 // don't provide a good way for the caller to determine if a conversion was
898 // successful.
wcstol_positive_strict(wchar_t * string,int * result)899 static bool wcstol_positive_strict(wchar_t *string, int *result) {
900   int value = 0;
901   for (wchar_t *c = string; *c != '\0'; ++c) {
902     int last_value = value;
903     value *= 10;
904     // Detect overflow.
905     if (value / 10 != last_value || value < 0) {
906       return false;
907     }
908     if (*c < '0' || *c > '9') {
909       return false;
910     }
911     unsigned int c_value = *c - '0';
912     last_value = value;
913     value += c_value;
914     // Detect overflow.
915     if (value < last_value) {
916       return false;
917     }
918     // Forbid leading zeroes unless the string is just "0".
919     if (value == 0 && *(c+1) != '\0') {
920       return false;
921     }
922   }
923   *result = value;
924   return true;
925 }
926 
FindPEFile()927 bool PDBSourceLineWriter::FindPEFile() {
928   CComPtr<IDiaSymbol> global;
929   if (FAILED(session_->get_globalScope(&global))) {
930     fprintf(stderr, "get_globalScope failed\n");
931     return false;
932   }
933 
934   CComBSTR symbols_file;
935   if (SUCCEEDED(global->get_symbolsFileName(&symbols_file))) {
936     wstring file(symbols_file);
937 
938     // Look for an EXE or DLL file.
939     const wchar_t *extensions[] = { L"exe", L"dll" };
940     for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) {
941       size_t dot_pos = file.find_last_of(L".");
942       if (dot_pos != wstring::npos) {
943         file.replace(dot_pos + 1, wstring::npos, extensions[i]);
944         // Check if this file exists.
945         if (GetFileAttributesW(file.c_str()) != INVALID_FILE_ATTRIBUTES) {
946           code_file_ = file;
947           return true;
948         }
949       }
950     }
951   }
952 
953   return false;
954 }
955 
956 // static
GetSymbolFunctionName(IDiaSymbol * function,BSTR * name,int * stack_param_size)957 bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function,
958                                                 BSTR *name,
959                                                 int *stack_param_size) {
960   *stack_param_size = -1;
961   const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS |
962                                    UNDNAME_NO_FUNCTION_RETURNS |
963                                    UNDNAME_NO_ALLOCATION_MODEL |
964                                    UNDNAME_NO_ALLOCATION_LANGUAGE |
965                                    UNDNAME_NO_THISTYPE |
966                                    UNDNAME_NO_ACCESS_SPECIFIERS |
967                                    UNDNAME_NO_THROW_SIGNATURES |
968                                    UNDNAME_NO_MEMBER_TYPE |
969                                    UNDNAME_NO_RETURN_UDT_MODEL |
970                                    UNDNAME_NO_ECSU;
971 
972   // Use get_undecoratedNameEx to get readable C++ names with arguments.
973   if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) {
974     if (function->get_name(name) != S_OK) {
975       fprintf(stderr, "failed to get function name\n");
976       return false;
977     }
978 
979     // It's possible for get_name to return an empty string, so
980     // special-case that.
981     if (wcscmp(*name, L"") == 0) {
982       SysFreeString(*name);
983       // dwarf_cu_to_module.cc uses "<name omitted>", so match that.
984       *name = SysAllocString(L"<name omitted>");
985       return true;
986     }
987 
988     // If a name comes from get_name because no undecorated form existed,
989     // it's already formatted properly to be used as output.  Don't do any
990     // additional processing.
991     //
992     // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's.
993     // This will result in calling get_name for some C++ symbols, so
994     // all of the parameter and return type information may not be included in
995     // the name string.
996   } else {
997     // C++ uses a bogus "void" argument for functions and methods that don't
998     // take any parameters.  Take it out of the undecorated name because it's
999     // ugly and unnecessary.
1000     const wchar_t *replace_string = L"(void)";
1001     const size_t replace_length = wcslen(replace_string);
1002     const wchar_t *replacement_string = L"()";
1003     size_t length = wcslen(*name);
1004     if (length >= replace_length) {
1005       wchar_t *name_end = *name + length - replace_length;
1006       if (wcscmp(name_end, replace_string) == 0) {
1007         WindowsStringUtils::safe_wcscpy(name_end, replace_length,
1008                                         replacement_string);
1009         length = wcslen(*name);
1010       }
1011     }
1012 
1013     // Undecorate names used for stdcall and fastcall.  These names prefix
1014     // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it
1015     // with '@' followed by the number of bytes of parameters, in decimal.
1016     // If such a name is found, take note of the size and undecorate it.
1017     // Only do this for names that aren't C++, which is determined based on
1018     // whether the undecorated name contains any ':' or '(' characters.
1019     if (!wcschr(*name, ':') && !wcschr(*name, '(') &&
1020         (*name[0] == '_' || *name[0] == '@')) {
1021       wchar_t *last_at = wcsrchr(*name + 1, '@');
1022       if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) {
1023         // If this function adheres to the fastcall convention, it accepts up
1024         // to the first 8 bytes of parameters in registers (%ecx and %edx).
1025         // We're only interested in the stack space used for parameters, so
1026         // so subtract 8 and don't let the size go below 0.
1027         if (*name[0] == '@') {
1028           if (*stack_param_size > 8) {
1029             *stack_param_size -= 8;
1030           } else {
1031             *stack_param_size = 0;
1032           }
1033         }
1034 
1035         // Undecorate the name by moving it one character to the left in its
1036         // buffer, and terminating it where the last '@' had been.
1037         WindowsStringUtils::safe_wcsncpy(*name, length,
1038                                          *name + 1, last_at - *name - 1);
1039      } else if (*name[0] == '_') {
1040         // This symbol's name is encoded according to the cdecl rules.  The
1041         // name doesn't end in a '@' character followed by a decimal positive
1042         // integer, so it's not a stdcall name.  Strip off the leading
1043         // underscore.
1044         WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length);
1045       }
1046     }
1047   }
1048 
1049   return true;
1050 }
1051 
1052 // static
GetFunctionStackParamSize(IDiaSymbol * function)1053 int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) {
1054   // This implementation is highly x86-specific.
1055 
1056   // Gather the symbols corresponding to data.
1057   CComPtr<IDiaEnumSymbols> data_children;
1058   if (FAILED(function->findChildren(SymTagData, NULL, nsNone,
1059                                     &data_children))) {
1060     return 0;
1061   }
1062 
1063   // lowest_base is the lowest %ebp-relative byte offset used for a parameter.
1064   // highest_end is one greater than the highest offset (i.e. base + length).
1065   // Stack parameters are assumed to be contiguous, because in reality, they
1066   // are.
1067   int lowest_base = INT_MAX;
1068   int highest_end = INT_MIN;
1069 
1070   CComPtr<IDiaSymbol> child;
1071   DWORD count;
1072   while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) {
1073     // If any operation fails at this point, just proceed to the next child.
1074     // Use the next_child label instead of continue because child needs to
1075     // be released before it's reused.  Declare constructable/destructable
1076     // types early to avoid gotos that cross initializations.
1077     CComPtr<IDiaSymbol> child_type;
1078 
1079     // DataIsObjectPtr is only used for |this|.  Because |this| can be passed
1080     // as a stack parameter, look for it in addition to traditional
1081     // parameters.
1082     DWORD child_kind;
1083     if (FAILED(child->get_dataKind(&child_kind)) ||
1084         (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) {
1085       goto next_child;
1086     }
1087 
1088     // Only concentrate on register-relative parameters.  Parameters may also
1089     // be enregistered (passed directly in a register), but those don't
1090     // consume any stack space, so they're not of interest.
1091     DWORD child_location_type;
1092     if (FAILED(child->get_locationType(&child_location_type)) ||
1093         child_location_type != LocIsRegRel) {
1094       goto next_child;
1095     }
1096 
1097     // Of register-relative parameters, the only ones that make any sense are
1098     // %ebp- or %esp-relative.  Note that MSVC's debugging information always
1099     // gives parameters as %ebp-relative even when a function doesn't use a
1100     // traditional frame pointer and stack parameters are accessed relative to
1101     // %esp, so just look for %ebp-relative parameters.  If you wanted to
1102     // access parameters, you'd probably want to treat these %ebp-relative
1103     // offsets as if they were relative to %esp before a function's prolog
1104     // executed.
1105     DWORD child_register;
1106     if (FAILED(child->get_registerId(&child_register)) ||
1107         child_register != CV_REG_EBP) {
1108       goto next_child;
1109     }
1110 
1111     LONG child_register_offset;
1112     if (FAILED(child->get_offset(&child_register_offset))) {
1113       goto next_child;
1114     }
1115 
1116     // IDiaSymbol::get_type can succeed but still pass back a NULL value.
1117     if (FAILED(child->get_type(&child_type)) || !child_type) {
1118       goto next_child;
1119     }
1120 
1121     ULONGLONG child_length;
1122     if (FAILED(child_type->get_length(&child_length))) {
1123       goto next_child;
1124     }
1125 
1126     int child_end = child_register_offset + static_cast<ULONG>(child_length);
1127     if (child_register_offset < lowest_base) {
1128       lowest_base = child_register_offset;
1129     }
1130     if (child_end > highest_end) {
1131       highest_end = child_end;
1132     }
1133 
1134 next_child:
1135     child.Release();
1136   }
1137 
1138   int param_size = 0;
1139   // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest
1140   // possible address to find a stack parameter before executing a function's
1141   // prolog (see above).  Some optimizations cause parameter offsets to be
1142   // lower than 4, but we're not concerned with those because we're only
1143   // looking for parameters contained in addresses higher than where the
1144   // return address is stored.
1145   if (lowest_base < 4) {
1146     lowest_base = 4;
1147   }
1148   if (highest_end > lowest_base) {
1149     // All stack parameters are pushed as at least 4-byte quantities.  If the
1150     // last type was narrower than 4 bytes, promote it.  This assumes that all
1151     // parameters' offsets are 4-byte-aligned, which is always the case.  Only
1152     // worry about the last type, because we're not summing the type sizes,
1153     // just looking at the lowest and highest offsets.
1154     int remainder = highest_end % 4;
1155     if (remainder) {
1156       highest_end += 4 - remainder;
1157     }
1158 
1159     param_size = highest_end - lowest_base;
1160   }
1161 
1162   return param_size;
1163 }
1164 
WriteMap(FILE * map_file)1165 bool PDBSourceLineWriter::WriteMap(FILE *map_file) {
1166   output_ = map_file;
1167 
1168   // Load the OMAP information, and disable auto-translation of addresses in
1169   // preference of doing it ourselves.
1170   OmapData omap_data;
1171   if (!GetOmapDataAndDisableTranslation(session_, &omap_data))
1172     return false;
1173   BuildImageMap(omap_data, &image_map_);
1174 
1175   bool ret = PrintPDBInfo();
1176   // This is not a critical piece of the symbol file.
1177   PrintPEInfo();
1178   ret = ret &&
1179       PrintSourceFiles() &&
1180       PrintFunctions() &&
1181       PrintFrameData();
1182 
1183   output_ = NULL;
1184   return ret;
1185 }
1186 
Close()1187 void PDBSourceLineWriter::Close() {
1188   session_.Release();
1189 }
1190 
GetModuleInfo(PDBModuleInfo * info)1191 bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) {
1192   if (!info) {
1193     return false;
1194   }
1195 
1196   info->debug_file.clear();
1197   info->debug_identifier.clear();
1198   info->cpu.clear();
1199 
1200   CComPtr<IDiaSymbol> global;
1201   if (FAILED(session_->get_globalScope(&global))) {
1202     return false;
1203   }
1204 
1205   DWORD machine_type;
1206   // get_machineType can return S_FALSE.
1207   if (global->get_machineType(&machine_type) == S_OK) {
1208     // The documentation claims that get_machineType returns a value from
1209     // the CV_CPU_TYPE_e enumeration, but that's not the case.
1210     // Instead, it returns one of the IMAGE_FILE_MACHINE values as
1211     // defined here:
1212     // http://msdn.microsoft.com/en-us/library/ms680313%28VS.85%29.aspx
1213     switch (machine_type) {
1214       case IMAGE_FILE_MACHINE_I386:
1215         info->cpu = L"x86";
1216         break;
1217       case IMAGE_FILE_MACHINE_AMD64:
1218         info->cpu = L"x86_64";
1219         break;
1220       default:
1221         info->cpu = L"unknown";
1222         break;
1223     }
1224   } else {
1225     // Unexpected, but handle gracefully.
1226     info->cpu = L"unknown";
1227   }
1228 
1229   // DWORD* and int* are not compatible.  This is clean and avoids a cast.
1230   DWORD age;
1231   if (FAILED(global->get_age(&age))) {
1232     return false;
1233   }
1234 
1235   bool uses_guid;
1236   if (!UsesGUID(&uses_guid)) {
1237     return false;
1238   }
1239 
1240   if (uses_guid) {
1241     GUID guid;
1242     if (FAILED(global->get_guid(&guid))) {
1243       return false;
1244     }
1245 
1246     // Use the same format that the MS symbol server uses in filesystem
1247     // hierarchies.
1248     wchar_t age_string[9];
1249     swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]),
1250              L"%x", age);
1251 
1252     // remove when VC++7.1 is no longer supported
1253     age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0';
1254 
1255     info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid);
1256     info->debug_identifier.append(age_string);
1257   } else {
1258     DWORD signature;
1259     if (FAILED(global->get_signature(&signature))) {
1260       return false;
1261     }
1262 
1263     // Use the same format that the MS symbol server uses in filesystem
1264     // hierarchies.
1265     wchar_t identifier_string[17];
1266     swprintf(identifier_string,
1267              sizeof(identifier_string) / sizeof(identifier_string[0]),
1268              L"%08X%x", signature, age);
1269 
1270     // remove when VC++7.1 is no longer supported
1271     identifier_string[sizeof(identifier_string) /
1272                       sizeof(identifier_string[0]) - 1] = L'\0';
1273 
1274     info->debug_identifier = identifier_string;
1275   }
1276 
1277   CComBSTR debug_file_string;
1278   if (FAILED(global->get_symbolsFileName(&debug_file_string))) {
1279     return false;
1280   }
1281   info->debug_file =
1282       WindowsStringUtils::GetBaseName(wstring(debug_file_string));
1283 
1284   return true;
1285 }
1286 
GetPEInfo(PEModuleInfo * info)1287 bool PDBSourceLineWriter::GetPEInfo(PEModuleInfo *info) {
1288   if (!info) {
1289     return false;
1290   }
1291 
1292   if (code_file_.empty() && !FindPEFile()) {
1293     fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
1294     return false;
1295   }
1296 
1297   // Convert wchar to native charset because ImageLoad only takes
1298   // a PSTR as input.
1299   string code_file;
1300   if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
1301     return false;
1302   }
1303 
1304   AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
1305   if (!img) {
1306     fprintf(stderr, "Failed to open PE file: %s\n", code_file.c_str());
1307     return false;
1308   }
1309 
1310   info->code_file = WindowsStringUtils::GetBaseName(code_file_);
1311 
1312   // The date and time that the file was created by the linker.
1313   DWORD TimeDateStamp = img->FileHeader->FileHeader.TimeDateStamp;
1314   // The size of the file in bytes, including all headers.
1315   DWORD SizeOfImage = 0;
1316   PIMAGE_OPTIONAL_HEADER64 opt =
1317     &((PIMAGE_NT_HEADERS64)img->FileHeader)->OptionalHeader;
1318   if (opt->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
1319     // 64-bit PE file.
1320     SizeOfImage = opt->SizeOfImage;
1321   } else {
1322     // 32-bit PE file.
1323     SizeOfImage = img->FileHeader->OptionalHeader.SizeOfImage;
1324   }
1325   wchar_t code_identifier[32];
1326   swprintf(code_identifier,
1327       sizeof(code_identifier) / sizeof(code_identifier[0]),
1328       L"%08X%X", TimeDateStamp, SizeOfImage);
1329   info->code_identifier = code_identifier;
1330 
1331   return true;
1332 }
1333 
UsesGUID(bool * uses_guid)1334 bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) {
1335   if (!uses_guid)
1336     return false;
1337 
1338   CComPtr<IDiaSymbol> global;
1339   if (FAILED(session_->get_globalScope(&global)))
1340     return false;
1341 
1342   GUID guid;
1343   if (FAILED(global->get_guid(&guid)))
1344     return false;
1345 
1346   DWORD signature;
1347   if (FAILED(global->get_signature(&signature)))
1348     return false;
1349 
1350   // There are two possibilities for guid: either it's a real 128-bit GUID
1351   // as identified in a code module by a new-style CodeView record, or it's
1352   // a 32-bit signature (timestamp) as identified by an old-style record.
1353   // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h.
1354   //
1355   // Because DIA doesn't provide a way to directly determine whether a module
1356   // uses a GUID or a 32-bit signature, this code checks whether the first 32
1357   // bits of guid are the same as the signature, and if the rest of guid is
1358   // zero.  If so, then with a pretty high degree of certainty, there's an
1359   // old-style CodeView record in use.  This method will only falsely find an
1360   // an old-style CodeView record if a real 128-bit GUID has its first 32
1361   // bits set the same as the module's signature (timestamp) and the rest of
1362   // the GUID is set to 0.  This is highly unlikely.
1363 
1364   GUID signature_guid = {signature};  // 0-initializes other members
1365   *uses_guid = !IsEqualGUID(guid, signature_guid);
1366   return true;
1367 }
1368 
1369 }  // namespace google_breakpad
1370