|  | // Copyright (c) 2006, Google Inc. | 
|  | // All rights reserved. | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are | 
|  | // met: | 
|  | // | 
|  | //     * Redistributions of source code must retain the above copyright | 
|  | // notice, this list of conditions and the following disclaimer. | 
|  | //     * Redistributions in binary form must reproduce the above | 
|  | // copyright notice, this list of conditions and the following disclaimer | 
|  | // in the documentation and/or other materials provided with the | 
|  | // distribution. | 
|  | //     * Neither the name of Google Inc. nor the names of its | 
|  | // contributors may be used to endorse or promote products derived from | 
|  | // this software without specific prior written permission. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  | // PDBSourceLineWriter uses a pdb file produced by Visual C++ to output | 
|  | // a line/address map for use with BasicSourceLineResolver. | 
|  |  | 
|  | #ifndef COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_ | 
|  | #define COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_ | 
|  |  | 
|  | #include <atlcomcli.h> | 
|  |  | 
|  | #include <string> | 
|  | #include <unordered_map> | 
|  |  | 
|  | #include "common/windows/module_info.h" | 
|  | #include "common/windows/omap.h" | 
|  |  | 
|  | struct IDiaEnumLineNumbers; | 
|  | struct IDiaSession; | 
|  | struct IDiaSymbol; | 
|  |  | 
|  | namespace google_breakpad { | 
|  |  | 
|  | using std::wstring; | 
|  | using std::unordered_map; | 
|  |  | 
|  | class PDBSourceLineWriter { | 
|  | public: | 
|  | enum FileFormat { | 
|  | PDB_FILE,  // a .pdb file containing debug symbols | 
|  | EXE_FILE,  // a .exe or .dll file | 
|  | ANY_FILE   // try PDB_FILE and then EXE_FILE | 
|  | }; | 
|  |  | 
|  | explicit PDBSourceLineWriter(); | 
|  | ~PDBSourceLineWriter(); | 
|  |  | 
|  | // Opens the given file.  For executable files, the corresponding pdb | 
|  | // file must be available; Open will be if it is not. | 
|  | // If there is already a pdb file open, it is automatically closed. | 
|  | // Returns true on success. | 
|  | bool Open(const wstring &file, FileFormat format); | 
|  |  | 
|  | // Closes the current pdb file and its associated resources. | 
|  | void Close(); | 
|  |  | 
|  | // Sets the code file full path.  This is optional for 32-bit modules.  It is | 
|  | // also optional for 64-bit modules when there is an executable file stored | 
|  | // in the same directory as the PDB file.  It is only required for 64-bit | 
|  | // modules when the executable file is not in the same location as the PDB | 
|  | // file and it must be called after Open() and before WriteMap(). | 
|  | // If Open() was called for an executable file, then it is an error to call | 
|  | // SetCodeFile() with a different file path and it will return false. | 
|  | bool SetCodeFile(const wstring &exe_file); | 
|  |  | 
|  | // Writes a Breakpad symbol file from the current pdb file to |symbol_file|. | 
|  | // Returns true on success. | 
|  | bool WriteSymbols(FILE *symbol_file); | 
|  |  | 
|  | // Retrieves information about the module's debugging file.  Returns | 
|  | // true on success and false on failure. | 
|  | bool GetModuleInfo(PDBModuleInfo *info); | 
|  |  | 
|  | // Retrieves information about the module's PE file.  Returns | 
|  | // true on success and false on failure. | 
|  | bool GetPEInfo(PEModuleInfo *info); | 
|  |  | 
|  | // Sets uses_guid to true if the opened file uses a new-style CodeView | 
|  | // record with a 128-bit GUID, or false if the opened file uses an old-style | 
|  | // CodeView record.  When no GUID is available, a 32-bit signature should be | 
|  | // used to identify the module instead.  If the information cannot be | 
|  | // determined, this method returns false. | 
|  | bool UsesGUID(bool *uses_guid); | 
|  |  | 
|  | private: | 
|  | // Outputs the line/address pairs for each line in the enumerator. | 
|  | // Returns true on success. | 
|  | bool PrintLines(IDiaEnumLineNumbers *lines); | 
|  |  | 
|  | // Outputs a function address and name, followed by its source line list. | 
|  | // block can be the same object as function, or it can be a reference to a | 
|  | // code block that is lexically part of this function, but resides at a | 
|  | // separate address. If has_multiple_symbols is true, this function's | 
|  | // instructions correspond to multiple symbols. Returns true on success. | 
|  | bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block, | 
|  | bool has_multiple_symbols); | 
|  |  | 
|  | // Outputs all functions as described above.  Returns true on success. | 
|  | bool PrintFunctions(); | 
|  |  | 
|  | // Outputs all of the source files in the session's pdb file. | 
|  | // Returns true on success. | 
|  | bool PrintSourceFiles(); | 
|  |  | 
|  | // Outputs all of the frame information necessary to construct stack | 
|  | // backtraces in the absence of frame pointers. For x86 data stored in | 
|  | // .pdb files. Returns true on success. | 
|  | bool PrintFrameDataUsingPDB(); | 
|  |  | 
|  | // Outputs all of the frame information necessary to construct stack | 
|  | // backtraces in the absence of frame pointers. For x64 data stored in | 
|  | // .exe, .dll files. Returns true on success. | 
|  | bool PrintFrameDataUsingEXE(); | 
|  |  | 
|  | // Outputs all of the frame information necessary to construct stack | 
|  | // backtraces in the absence of frame pointers.  Returns true on success. | 
|  | bool PrintFrameData(); | 
|  |  | 
|  | // Outputs a single public symbol address and name, if the symbol corresponds | 
|  | // to a code address.  Returns true on success.  If symbol is does not | 
|  | // correspond to code, returns true without outputting anything. If | 
|  | // has_multiple_symbols is true, the symbol corresponds to a code address and | 
|  | // the instructions correspond to multiple symbols. | 
|  | bool PrintCodePublicSymbol(IDiaSymbol *symbol, bool has_multiple_symbols); | 
|  |  | 
|  | // Outputs a line identifying the PDB file that is being dumped, along with | 
|  | // its uuid and age. | 
|  | bool PrintPDBInfo(); | 
|  |  | 
|  | // Outputs a line identifying the PE file corresponding to the PDB | 
|  | // file that is being dumped, along with its code identifier, | 
|  | // which consists of its timestamp and file size. | 
|  | bool PrintPEInfo(); | 
|  |  | 
|  | // Returns true if this filename has already been seen, | 
|  | // and an ID is stored for it, or false if it has not. | 
|  | bool FileIDIsCached(const wstring &file) { | 
|  | return unique_files_.find(file) != unique_files_.end(); | 
|  | } | 
|  |  | 
|  | // Cache this filename and ID for later reuse. | 
|  | void CacheFileID(const wstring &file, DWORD id) { | 
|  | unique_files_[file] = id; | 
|  | } | 
|  |  | 
|  | // Store this ID in the cache as a duplicate for this filename. | 
|  | void StoreDuplicateFileID(const wstring &file, DWORD id) { | 
|  | unordered_map<wstring, DWORD>::iterator iter = unique_files_.find(file); | 
|  | if (iter != unique_files_.end()) { | 
|  | // map this id to the previously seen one | 
|  | file_ids_[id] = iter->second; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Given a file's unique ID, return the ID that should be used to | 
|  | // reference it. There may be multiple files with identical filenames | 
|  | // but different unique IDs. The cache attempts to coalesce these into | 
|  | // one ID per unique filename. | 
|  | DWORD GetRealFileID(DWORD id) { | 
|  | unordered_map<DWORD, DWORD>::iterator iter = file_ids_.find(id); | 
|  | if (iter == file_ids_.end()) | 
|  | return id; | 
|  | return iter->second; | 
|  | } | 
|  |  | 
|  | // Find the PE file corresponding to the loaded PDB file, and | 
|  | // set the code_file_ member. Returns false on failure. | 
|  | bool FindPEFile(); | 
|  |  | 
|  | // Returns the function name for a symbol.  If possible, the name is | 
|  | // undecorated.  If the symbol's decorated form indicates the size of | 
|  | // parameters on the stack, this information is returned in stack_param_size. | 
|  | // Returns true on success.  If the symbol doesn't encode parameter size | 
|  | // information, stack_param_size is set to -1. | 
|  | static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name, | 
|  | int *stack_param_size); | 
|  |  | 
|  | // Returns the number of bytes of stack space used for a function's | 
|  | // parameters.  function must have the tag SymTagFunction.  In the event of | 
|  | // a failure, returns 0, which is also a valid number of bytes. | 
|  | static int GetFunctionStackParamSize(IDiaSymbol *function); | 
|  |  | 
|  | // The filename of the PE file corresponding to the currently-open | 
|  | // pdb file. | 
|  | wstring code_file_; | 
|  |  | 
|  | // The session for the currently-open pdb file. | 
|  | CComPtr<IDiaSession> session_; | 
|  |  | 
|  | // The current output file for this WriteMap invocation. | 
|  | FILE *output_; | 
|  |  | 
|  | // There may be many duplicate filenames with different IDs. | 
|  | // This maps from the DIA "unique ID" to a single ID per unique | 
|  | // filename. | 
|  | unordered_map<DWORD, DWORD> file_ids_; | 
|  | // This maps unique filenames to file IDs. | 
|  | unordered_map<wstring, DWORD> unique_files_; | 
|  |  | 
|  | // This is used for calculating post-transform symbol addresses and lengths. | 
|  | ImageMap image_map_; | 
|  |  | 
|  | // Disallow copy ctor and operator= | 
|  | PDBSourceLineWriter(const PDBSourceLineWriter&); | 
|  | void operator=(const PDBSourceLineWriter&); | 
|  | }; | 
|  |  | 
|  | }  // namespace google_breakpad | 
|  |  | 
|  | #endif  // COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_ |