xref: /aosp_15_r20/external/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2007 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // ms_symbol_server_converter.h: Obtain symbol files from a Microsoft
30 // symbol server, and convert them to Breakpad's dumped format.
31 //
32 // At runtime, MSSymbolServerConverter and code that it calls depend on being
33 // able to locate suitable versions of dbghelp.dll and symsrv.dll.  For best
34 // results, place these files in the same directory as the executable.
35 // dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are
36 // both redistributable, as indicated by the package's redist.txt file.
37 //
38 // When connecting to Microsoft's symbol server at
39 // http://msdl.microsoft.com/download/symbols/, which provides access to
40 // symbols for the operating system itself, symsrv.dll requires agreement to
41 // Microsoft's "Terms of Use for Microsoft Symbols and Binaries."  Because this
42 // library places the symbol engine into a promptless mode, the dialog with the
43 // terms will not appear, and use of Microsoft's symbol server will not be
44 // possible.  To indicate agreement to the terms, create a file called
45 // symsrv.yes in the same directory as symsrv.dll.  (Note that symsrv.dll will
46 // also recognize a symsrv.no file as indicating that you do not accept the
47 // terms; the .yes file takes priority over the .no file.)  The terms of use
48 // are contained within symsrv.dll; they were formerly available online at
49 // http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but
50 // do not appear to be available online any longer as of January, 2007.  It is
51 // possible to view the terms from within WinDbg (Debugging Tools for Windows)
52 // by removing any symsrv.yes and symsrv.no files from WinDbg's directory,
53 // setting the symbol path to include Microsoft's symbol server (.sympath), and
54 // attempting to load symbols from their server (.reload).
55 //
56 // This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8,
57 // included with Microsoft Visual Studio 8 in Common7/IDE.  This has also been
58 // tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633,
59 // included with the same versions of Debugging Tools for Windows, available at
60 // http://www.microsoft.com/whdc/devtools/debugging/ .
61 //
62 // Author: Mark Mentovai
63 
64 #ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
65 #define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
66 
67 #include <windows.h>
68 
69 #include <string>
70 #include <vector>
71 
72 namespace google_breakpad {
73 
74 using std::string;
75 using std::vector;
76 
77 // MissingSymbolInfo contains the subset of the information in the processor's
78 // CodeModule structure relevant to obtaining a missing symbol file.  Only
79 // debug_file and debug_identifier are relevant in actually obtaining the
80 // missing file; the other fields are for convenience.
81 struct MissingSymbolInfo {
82   string code_file;
83   string code_identifier;
84   string debug_file;
85   string debug_identifier;
86   string version;
87 };
88 
89 class GUIDOrSignatureIdentifier {
90  public:
91   enum GUIDOrSignatureType {
92     TYPE_NONE = 0,
93     TYPE_GUID,
94     TYPE_SIGNATURE
95   };
96 
GUIDOrSignatureIdentifier()97   GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {}
98 
99   // Converts |identifier|, a debug_identifier-formatted string, into its
100   // component fields: either a GUID and age, or signature and age.  If
101   // successful, sets the relevant fields in the object, including the type
102   // field, and returns true.  On error, returns false.
103   bool InitializeFromString(const string& identifier);
104 
type()105   GUIDOrSignatureType type() const { return type_; }
guid()106   GUID guid() const { return guid_; }
signature()107   DWORD signature() const { return signature_; }
age()108   int age() const { return age_; }
guid_or_signature_pointer()109   const void* guid_or_signature_pointer() const { return &guid_; }
110 
111  private:
112   GUIDOrSignatureType type_;
113 
114   // An identifier contains either a 128-bit uuid or a 32-bit signature.
115   union {
116     GUID guid_;
117     DWORD signature_;
118   };
119 
120   // All identifiers used here have age fields, which indicate a specific
121   // revision given a uuid or signature.
122   int age_;
123 };
124 
125 class MSSymbolServerConverter {
126  public:
127   enum LocateResult {
128     LOCATE_FAILURE = 0,
129     LOCATE_NOT_FOUND,  // Authoritative: the file is not present.
130     LOCATE_RETRY,      // Transient (network?) error, try again later.
131     LOCATE_SUCCESS,
132     LOCATE_HTTP_HTTPS_REDIR
133   };
134 
135   // Create a new object.  local_cache is the location (pathname) of a local
136   // symbol store used to hold downloaded and converted symbol files.  This
137   // directory will be created by LocateSymbolFile when it successfully
138   // retrieves a symbol file. symbol_servers contains a list of locations (URLs
139   // or pathnames) of the upstream symbol server stores, given in order of
140   // preference, with the first string in the vector identifying the first
141   // store to try.  The vector must contain at least one string.  None of the
142   // strings passed to this constructor may contain asterisk ('*') or semicolon
143   // (';') characters, as the symbol engine uses these characters as separators.
144   // If |trace_symsrv| is set then callbacks from SymSrv will be logged to
145   // stderr.
146   MSSymbolServerConverter(const string& local_cache,
147                           const vector<string>& symbol_servers,
148                           bool trace_symsrv);
149 
150   // Locates the PE file (DLL or EXE) specified by the identifying information
151   // in |missing|, by checking the symbol stores identified when the object
152   // was created.  When returning LOCATE_SUCCESS, pe_file is set to
153   // the pathname of the decompressed PE file as it is stored in the
154   // local cache.
155   LocateResult LocatePEFile(const MissingSymbolInfo& missing, string* pe_file);
156 
157   // Locates the symbol file specified by the identifying information in
158   // |missing|, by checking the symbol stores identified when the object
159   // was created.  When returning LOCATE_SUCCESS, symbol_file is set to
160   // the pathname of the decompressed symbol file as it is stored in the
161   // local cache.
162   LocateResult LocateSymbolFile(const MissingSymbolInfo& missing,
163                                 string* symbol_file);
164 
165   // Calls LocateSymbolFile and converts the returned symbol file to the
166   // dumped-symbol format, storing it adjacent to the symbol file.  The
167   // only conversion supported is from pdb files.  Returns the return
168   // value of LocateSymbolFile, or if LocateSymbolFile succeeds but
169   // conversion fails, returns LOCATE_FAILURE.  The pathname to the
170   // pdb file and to the converted symbol file are returned in
171   // |converted_symbol_file|, |symbol_file|, and |pe_file|.  |symbol_file| and
172   // |pe_file| are optional and may be NULL.  If only the converted symbol file
173   // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate
174   // that the original symbol file (pdb) and executable file (exe, dll) should
175   // be deleted after conversion.
176   LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo& missing,
177                                           bool keep_symbol_file,
178                                           bool keep_pe_file,
179                                           string* converted_symbol_file,
180                                           string* symbol_file,
181                                           string* pe_file);
182 
183   // Calls LocatePEFile and converts the returned PE file to the
184   // dumped-symbol format, storing it adjacent to the PE file. The
185   // only conversion supported is from PE files. Returns the return
186   // value of LocatePEFile, or if LocatePEFile succeeds but
187   // conversion fails, returns LOCATE_FAILURE. The pathname to the
188   // PE file and to the converted symbol file are returned in
189   // |converted_symbol_file| and |pe_file|. |pe_file| is optional and may be
190   // NULL.  If only the converted symbol file is desired, set |keep_pe_file|
191   // to false to indicate that the executable file (exe, dll) should be deleted
192   // after conversion.
193   // NOTE: Currrently only supports x64 PEs.
194   LocateResult LocateAndConvertPEFile(const MissingSymbolInfo& missing,
195                                       bool keep_pe_file,
196                                       string* converted_symbol_file,
197                                       string* pe_file);
198 
199  private:
200   // Locates the PDB or PE file (DLL or EXE) specified by the identifying
201   // information in |debug_or_code_file| and |debug_or_code_id|, by checking
202   // the symbol stores identified when the object was created.  When
203   // returning LOCATE_SUCCESS, file_name is set to the pathname of the
204   // decompressed PDB or PE file file as it is stored in the local cache.
205   LocateResult LocateFile(const string& debug_or_code_file,
206                           const string& debug_or_code_id,
207                           const string& version, string* file_name);
208 
209   // Called by various SymSrv functions to report status as progress is made
210   // and to allow the callback to influence processing.  Messages sent to this
211   // callback can be used to distinguish between the various failure modes
212   // that SymFindFileInPath might encounter.
213   static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data,
214                                    ULONG64 context);
215 
216   // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate
217   // symbol file is located, when it's present in the local cache.
218   // SymFindFileInPath actually seems to accept NULL for a callback function
219   // and behave properly for our needs in that case, but the documentation
220   // doesn't mention it, so this little callback is provided.
221   static BOOL CALLBACK SymFindFileInPathCallback(const char* filename,
222                                                  void* context);
223 
224   // The search path used by SymSrv, built based on the arguments to the
225   // constructor.
226   string symbol_path_;
227 
228   // SymCallback will set at least one of these failure variables if
229   // SymFindFileInPath fails for an expected reason.
230   bool fail_dns_;        // DNS failures (fail_not_found_ will also be set).
231   bool fail_timeout_;    // Timeouts (fail_not_found_ will also be set).
232   bool fail_http_https_redir_;  // Bad URL-- we should be using HTTPS.
233   bool fail_not_found_;  // The file could not be found.  If this is the only
234                          // fail_* member set, then it is authoritative.
235 
236   // If set then callbacks from SymSrv will be logged to stderr.
237   bool trace_symsrv_;
238 };
239 
240 }  // namespace google_breakpad
241 
242 #endif  // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
243