aboutsummaryrefslogtreecommitdiff
path: root/src/tools/windows/converter/ms_symbol_server_converter.h
blob: 40d65d52a7e01d1367fe4d9c816e9fd763eb5f05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// Copyright (c) 2007, 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.

// ms_symbol_server_converter.h: Obtain symbol files from a Microsoft
// symbol server, and convert them to Breakpad's dumped format.
//
// At runtime, MSSymbolServerConverter and code that it calls depend on being
// able to locate suitable versions of dbghelp.dll and symsrv.dll.  For best
// results, place these files in the same directory as the executable.
// dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are
// both redistributable, as indicated by the package's redist.txt file.
//
// When connecting to Microsoft's symbol server at
// http://msdl.microsoft.com/download/symbols/, which provides access to
// symbols for the operating system itself, symsrv.dll requires agreement to
// Microsoft's "Terms of Use for Microsoft Symbols and Binaries."  Because this
// library places the symbol engine into a promptless mode, the dialog with the
// terms will not appear, and use of Microsoft's symbol server will not be
// possible.  To indicate agreement to the terms, create a file called
// symsrv.yes in the same directory as symsrv.dll.  (Note that symsrv.dll will
// also recognize a symsrv.no file as indicating that you do not accept the
// terms; the .yes file takes priority over the .no file.)  The terms of use
// are contained within symsrv.dll; they were formerly available online at
// http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but
// do not appear to be available online any longer as of January, 2007.  It is
// possible to view the terms from within WinDbg (Debugging Tools for Windows)
// by removing any symsrv.yes and symsrv.no files from WinDbg's directory,
// setting the symbol path to include Microsoft's symbol server (.sympath), and
// attempting to load symbols from their server (.reload).
//
// This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8,
// included with Microsoft Visual Studio 8 in Common7/IDE.  This has also been
// tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633,
// included with the same versions of Debugging Tools for Windows, available at
// http://www.microsoft.com/whdc/devtools/debugging/ .
//
// Author: Mark Mentovai

#ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
#define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_

#include <windows.h>

#include <string>
#include <vector>

namespace google_breakpad {

using std::string;
using std::vector;

// MissingSymbolInfo contains the subset of the information in the processor's
// CodeModule structure relevant to obtaining a missing symbol file.  Only
// debug_file and debug_identifier are relevant in actually obtaining the
// missing file; the other fields are for convenience.
struct MissingSymbolInfo {
  string code_file;
  string code_identifier;
  string debug_file;
  string debug_identifier;
  string version;
};

class GUIDOrSignatureIdentifier {
 public:
  enum GUIDOrSignatureType {
    TYPE_NONE = 0,
    TYPE_GUID,
    TYPE_SIGNATURE
  };

  GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {}

  // Converts |identifier|, a debug_identifier-formatted string, into its
  // component fields: either a GUID and age, or signature and age.  If
  // successful, sets the relevant fields in the object, including the type
  // field, and returns true.  On error, returns false.
  bool InitializeFromString(const string& identifier);

  GUIDOrSignatureType type() const { return type_; }
  GUID guid() const { return guid_; }
  DWORD signature() const { return signature_; }
  int age() const { return age_; }
  const void* guid_or_signature_pointer() const { return &guid_; }

 private:
  GUIDOrSignatureType type_;

  // An identifier contains either a 128-bit uuid or a 32-bit signature.
  union {
    GUID guid_;
    DWORD signature_;
  };

  // All identifiers used here have age fields, which indicate a specific
  // revision given a uuid or signature.
  int age_;
};

class MSSymbolServerConverter {
 public:
  enum LocateResult {
    LOCATE_FAILURE = 0,
    LOCATE_NOT_FOUND,    // Authoritative: the file is not present.
    LOCATE_RETRY,        // Transient (network?) error, try again later.
    LOCATE_SUCCESS
  };

  // Create a new object.  local_cache is the location (pathname) of a local
  // symbol store used to hold downloaded and converted symbol files.  This
  // directory will be created by LocateSymbolFile when it successfully
  // retrieves a symbol file. symbol_servers contains a list of locations (URLs
  // or pathnames) of the upstream symbol server stores, given in order of
  // preference, with the first string in the vector identifying the first
  // store to try.  The vector must contain at least one string.  None of the
  // strings passed to this constructor may contain asterisk ('*') or semicolon
  // (';') characters, as the symbol engine uses these characters as separators.
  MSSymbolServerConverter(const string& local_cache,
                          const vector<string>& symbol_servers);

  // Locates the PE file (DLL or EXE) specified by the identifying information
  // in |missing|, by checking the symbol stores identified when the object
  // was created.  When returning LOCATE_SUCCESS, pe_file is set to
  // the pathname of the decompressed PE file as it is stored in the
  // local cache.
  LocateResult LocatePEFile(const MissingSymbolInfo& missing, string* pe_file);

  // Locates the symbol file specified by the identifying information in
  // |missing|, by checking the symbol stores identified when the object
  // was created.  When returning LOCATE_SUCCESS, symbol_file is set to
  // the pathname of the decompressed symbol file as it is stored in the
  // local cache.
  LocateResult LocateSymbolFile(const MissingSymbolInfo& missing,
                                string* symbol_file);

  // Calls LocateSymbolFile and converts the returned symbol file to the
  // dumped-symbol format, storing it adjacent to the symbol file.  The
  // only conversion supported is from pdb files.  Returns the return
  // value of LocateSymbolFile, or if LocateSymbolFile succeeds but
  // conversion fails, returns LOCATE_FAILURE.  The pathname to the
  // pdb file and to the converted symbol file are returned in
  // |converted_symbol_file|, |symbol_file|, and |pe_file|.  |symbol_file| and
  // |pe_file| are optional and may be NULL.  If only the converted symbol file
  // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate
  // that the original symbol file (pdb) and executable file (exe, dll) should
  // be deleted after conversion.
  LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo& missing,
                                          bool keep_symbol_file,
                                          bool keep_pe_file,
                                          string* converted_symbol_file,
                                          string* symbol_file,
                                          string* pe_file);

  // Calls LocatePEFile and converts the returned PE file to the
  // dumped-symbol format, storing it adjacent to the PE file. The
  // only conversion supported is from PE files. Returns the return
  // value of LocatePEFile, or if LocatePEFile succeeds but
  // conversion fails, returns LOCATE_FAILURE. The pathname to the
  // PE file and to the converted symbol file are returned in
  // |converted_symbol_file| and |pe_file|. |pe_file| is optional and may be
  // NULL.  If only the converted symbol file is desired, set |keep_pe_file|
  // to false to indicate that the executable file (exe, dll) should be deleted
  // after conversion.
  // NOTE: Currrently only supports x64 PEs.
  LocateResult LocateAndConvertPEFile(const MissingSymbolInfo& missing,
                                      bool keep_pe_file,
                                      string* converted_symbol_file,
                                      string* pe_file);

 private:
  // Locates the PDB or PE file (DLL or EXE) specified by the identifying
  // information in |debug_or_code_file| and |debug_or_code_id|, by checking
  // the symbol stores identified when the object was created.  When
  // returning LOCATE_SUCCESS, file_name is set to the pathname of the
  // decompressed PDB or PE file file as it is stored in the local cache.
  LocateResult LocateFile(const string& debug_or_code_file,
                          const string& debug_or_code_id,
                          const string& version, string* file_name);

  // Called by various SymSrv functions to report status as progress is made
  // and to allow the callback to influence processing.  Messages sent to this
  // callback can be used to distinguish between the various failure modes
  // that SymFindFileInPath might encounter.
  static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data,
                                   ULONG64 context);

  // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate
  // symbol file is located, when it's present in the local cache.
  // SymFindFileInPath actually seems to accept NULL for a callback function
  // and behave properly for our needs in that case, but the documentation
  // doesn't mention it, so this little callback is provided.
  static BOOL CALLBACK SymFindFileInPathCallback(const char* filename,
                                                 void* context);

  // The search path used by SymSrv, built based on the arguments to the
  // constructor.
  string symbol_path_;

  // SymCallback will set at least one of these failure variables if
  // SymFindFileInPath fails for an expected reason.
  bool fail_dns_;        // DNS failures (fail_not_found_ will also be set).
  bool fail_timeout_;    // Timeouts (fail_not_found_ will also be set).
  bool fail_not_found_;  // The file could not be found.  If this is the only
                         // fail_* member set, then it is authoritative.
};

}  // namespace google_breakpad

#endif  // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_