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