1 : // Copyright 2011 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares some utilities for dealing with PDB files via the DIA interface.
16 : #ifndef SYZYGY_PE_DIA_UTIL_H_
17 : #define SYZYGY_PE_DIA_UTIL_H_
18 :
19 : #include <windows.h> // NOLINT
20 : #include <dia2.h>
21 : #include <vector>
22 :
23 : #include "base/callback.h"
24 : #include "base/files/file_path.h"
25 : #include "base/strings/string16.h"
26 : #include "base/win/scoped_comptr.h"
27 :
28 m : namespace pe {
29 :
30 : // The name of the DIA SDK DLL.
31 m : extern const wchar_t kDiaDllName[];
32 :
33 : // The names of various debug streams.
34 m : extern const wchar_t kFixupDiaDebugStreamName[];
35 m : extern const wchar_t kOmapToDiaDebugStreamName[];
36 m : extern const wchar_t kOmapFromDiaDebugStreamName[];
37 :
38 : // A trinary value that is returned by search routines.
39 m : enum SearchResult {
40 : // The search completed and the object was found.
41 m : kSearchSucceeded,
42 : // The search completed, but the object was not found.
43 m : kSearchFailed,
44 : // The search did not complete due to an error.
45 m : kSearchErrored,
46 m : };
47 :
48 m : namespace internal {
49 :
50 : // Creates a Dia object and request an interface on it. Logs any errors.
51 : //
52 : // @param created_source pointer that will receive the created object.
53 : // @param class_id the class interface ID for the object that we want to create.
54 : // @param interface_identifier the interface ID for the object that we want to
55 : // create.
56 : // @returns true on success, false otherwise.
57 m : bool CreateDiaObject(void** created_object, const CLSID& class_id,
58 m : const IID& interface_identifier);
59 :
60 m : } // namespace internal
61 :
62 : // Creates a Dia object and request an interface on it. Logs any errors.
63 : //
64 : // @tparam T the interface type.
65 : // @param created_source pointer that will receive the created object.
66 : // @param class_id the class interface ID for the object that we want to create.
67 : // @returns true on success, false otherwise.
68 m : template <typename T>
69 m : bool CreateDiaObject(T** created_object, const CLSID& class_id);
70 :
71 : // Creates a DiaDataSource object. Logs any errors.
72 : //
73 : // @param created_source pointer that will receive the created object.
74 : // @returns true on success, false otherwise.
75 m : bool CreateDiaSource(IDiaDataSource** created_source);
76 :
77 : // Creates a dia session for the provided object. Logs any errors.
78 : //
79 : // @param file the file to open.
80 : // @param dia_source the DIA source to use.
81 : // @param dia_session pointer that will receive the created DIA session.
82 : // @returns true on success, false otherwise.
83 m : bool CreateDiaSession(const base::FilePath& file,
84 m : IDiaDataSource* dia_source,
85 m : IDiaSession** dia_session);
86 :
87 : // Find the table with the given IID. Logs any errors.
88 : //
89 : // @param iid the IID of the table to look for.
90 : // @param dia_session the DIA session whose tables are to be queried.
91 : // @param out_table a pointer to the object to receive the table. If the table
92 : // is not found this will be NULL on return.
93 : // @returns a SearchResult
94 m : SearchResult FindDiaTable(const IID& iid,
95 m : IDiaSession* dia_session,
96 m : void** out_table);
97 :
98 : // Find the table that can be cast to the given Dia interface. Logs any errors.
99 : //
100 : // @tparam T an IDia* interface.
101 : // @param session the DIA session whose tables are to be queried.
102 : // @param out_table a pointer to the object to receive the table. If the table
103 : // is not found this will be NULL on return.
104 : // @returns a SearchResult
105 m : template <typename T>
106 m : SearchResult FindDiaTable(IDiaSession* dia_session, T** out_table);
107 :
108 : // Finds teh debug stream with the given name. Logs any errors.
109 : //
110 : // @param name the name of the stream to find.
111 : // @param dia_session the DIA session to search.
112 : // @param dia_debug_stream the pointer that will receive the debug stream, if
113 : // found.
114 : // @returns a SearchResult.
115 m : SearchResult FindDiaDebugStream(const wchar_t* name,
116 m : IDiaSession* dia_session,
117 m : IDiaEnumDebugStreamData** dia_debug_stream);
118 :
119 : // This reads a given debug stream into the provided vector. The type T
120 : // must be the same size as the debug stream record size. Logs any errors.
121 : //
122 : // @tparam T the type of object to read from the debug stream.
123 : // @param stream the debug stream from which to read objects.
124 : // @param list the list to be populated.
125 : // @returns true on success, false otherwise.
126 m : template <typename T>
127 m : bool LoadDiaDebugStream(IDiaEnumDebugStreamData* stream, std::vector<T>* list);
128 :
129 : // This loads the named debug stream into the provided vector. The type T must
130 : // be the same size as the debug stream record size. Logs any errors.
131 : //
132 : // @tparam T the type of object to read from the debug stream.
133 : // @param name the name of the stream to load.
134 : // @param dia_session the DIA session to search.
135 : // @param list the list to be populated.
136 : // @returns a SearchResults.
137 m : template <typename T>
138 m : SearchResult FindAndLoadDiaDebugStreamByName(const wchar_t* name,
139 m : IDiaSession* dia_session,
140 m : std::vector<T>* list);
141 :
142 : // Gets the index id associated with the given symbol.
143 : // @param symbol the symbol to examine.
144 : // @param sym_index_id on success, returns @p symbol's index id.
145 : // @returns true on success, false on failure.
146 m : bool GetSymIndexId(IDiaSymbol* symbol, uint32_t* sym_index_id);
147 :
148 : // Gets the symbol tab associated with the given symbol.
149 : // @param symbol the symbol to examine.
150 : // @param sym_tag on success, returns @p symbol's tag.
151 : // @returns true on success, false on failure.
152 m : bool GetSymTag(IDiaSymbol* symbol, enum SymTagEnum* sym_tag);
153 :
154 : // Checks to see if the given symbol is of the expected type.
155 : // @returns true if @p symbol is of type @p expected_sym_tag,
156 : // false on error or mismatch.
157 m : bool IsSymTag(IDiaSymbol* symbol, enum SymTagEnum expected_sym_tag);
158 :
159 : // Gets the name associated with the given symbol.
160 : // @param symbol the symbol to examine.
161 : // @param name on success, returns @p symbol's name.
162 : // @returns true on success, false on failure.
163 m : bool GetSymName(IDiaSymbol* symbol, base::string16* name);
164 :
165 : // Gets the undecorated name associated with the given symbol.
166 : // @param symbol the symbol to examine.
167 : // @param name on success, returns @p symbol's undecorated name.
168 : // @returns true on success, false on failure.
169 m : bool GetSymUndecoratedName(IDiaSymbol* symbol, base::string16* name);
170 :
171 : // Gets the symbol's data kind.
172 : // @param symbol the symbol to examine.
173 : // @param kind on success, returns @p symbol's data kind.
174 : // @returns true on success, false on failure.
175 m : bool GetDataKind(IDiaSymbol* symbol, enum DataKind* kind);
176 :
177 : // Gets the symbol's location type.
178 : // @param symbol the symbol to examine.
179 : // @param location_type on success, returns @p symbol's location type.
180 : // @returns true on success, false on failure.
181 m : bool GetLocationType(IDiaSymbol* symbol, enum LocationType* location_type);
182 :
183 : // Gets the symbol's register id.
184 : // @param symbol the symbol to examine.
185 : // @param register_id on success, returns @p symbol's register id.
186 : // @returns true on success, false on failure.
187 m : bool GetRegisterId(IDiaSymbol* symbol, uint32_t* register_id);
188 :
189 : // Gets the symbol's offset.
190 : // @param symbol the symbol to examine.
191 : // @param offset on success, returns @p symbol's offset.
192 : // @returns true on success, false on failure.
193 m : bool GetSymOffset(IDiaSymbol* symbol, ptrdiff_t* offset);
194 :
195 : // Gets the symbol's type.
196 : // @param symbol the symbol to examine.
197 : // @param type on success, returns @p symbol's type.
198 : // @returns true on success, false on failure.
199 m : bool GetSymType(IDiaSymbol* symbol, base::win::ScopedComPtr<IDiaSymbol>* type);
200 :
201 : // Gets the symbol's CV qualifiers.
202 : // @param symbol the symbol to examine.
203 : // @param is_const on success, returns whether @p symbol is const qualified.
204 : // @param is_volatile on success, returns whether @p symbol is volatile
205 : // qualified.
206 : // @returns true on success, false on failure.
207 m : bool GetSymQualifiers(IDiaSymbol* symbol, bool* is_const, bool* is_volatile);
208 :
209 : // Gets the number of items contained by the type.
210 : // @param symbol the symbol to examine.
211 : // @param count on success, returns the number of items.
212 : // @returns true on success, false on failure.
213 m : bool GetSymCount(IDiaSymbol* symbol, size_t* count);
214 :
215 : // Gets the symbol's class parent.
216 : // @param symbol the symbol to examine.
217 : // @param parent on success, returns @p symbol's class parent or nullptr if the
218 : // parent property is no available for the symbol.
219 : // @returns true on success, false on failure.
220 m : bool GetSymClassParent(IDiaSymbol* symbol,
221 m : base::win::ScopedComPtr<IDiaSymbol>* parent);
222 :
223 : // Gets the symbol's lexical parent.
224 : // @param symbol the symbol to examine.
225 : // @param parent on success, returns @p symbol's lexical parent.
226 : // @returns true on success, false on failure.
227 m : bool GetSymLexicalParent(IDiaSymbol* symbol,
228 m : base::win::ScopedComPtr<IDiaSymbol>* parent);
229 :
230 : // Gets the frame's base address.
231 : // @param frame the stack frame.
232 : // @param frame_base on success, returns @p frame's base address.
233 : // @returns true on sucess, false on failure.
234 m : bool GetFrameBase(IDiaStackFrame* frame, uint64_t* frame_base);
235 :
236 : // Gets a register's value for the frame.
237 : // @param frame the stack frame.
238 : // @param register_index the index of the desired register.
239 : // @param frame_base on success, returns the register's value.
240 : // @returns true on sucess, false on failure.
241 m : bool GetRegisterValue(IDiaStackFrame* frame,
242 m : CV_HREG_e register_index,
243 m : uint64_t* register_value);
244 :
245 : // Gets the stack frame's size.
246 : // @param frame the stack frame.
247 : // @param frame_size on success, returns @p frame's size.
248 : // @returns true on sucess, false on failure.
249 m : bool GetSize(IDiaStackFrame* frame, uint32_t* frame_size);
250 :
251 : // Gets the stack frame's locals base address.
252 : // @param frame the stack frame.
253 : // @param size on success, returns the base address of the locals.
254 : // @returns true on sucess, false on failure.
255 m : bool GetLocalsBase(IDiaStackFrame* frame, uint64_t* locals_base);
256 :
257 : // A worker class that makes it easy to visit specific children of a given
258 : // DIA symbol.
259 m : class ChildVisitor {
260 m : public:
261 m : typedef base::Callback<bool(IDiaSymbol*)> VisitSymbolCallback;
262 :
263 : // Creates a visitor for the children of @p parent of type @p type.
264 m : ChildVisitor(IDiaSymbol* parent, enum SymTagEnum type);
265 :
266 : // Visits all children of type type, of parent symbol,
267 : // calling @p child_callback for each.
268 : // @returns true on success.
269 m : bool VisitChildren(const VisitSymbolCallback& child_callback);
270 :
271 m : private:
272 m : bool VisitChildrenImpl();
273 m : bool EnumerateChildren(IDiaEnumSymbols* children);
274 m : bool VisitChild(IDiaSymbol* child);
275 :
276 m : base::win::ScopedComPtr<IDiaSymbol> parent_;
277 m : enum SymTagEnum type_;
278 :
279 m : const VisitSymbolCallback* child_callback_;
280 :
281 m : DISALLOW_COPY_AND_ASSIGN(ChildVisitor);
282 m : };
283 :
284 : // A worker class that makes it easy to visit each compiland in
285 : // in a given DIA session.
286 m : class CompilandVisitor {
287 m : public:
288 m : typedef ChildVisitor::VisitSymbolCallback VisitCompilandCallback;
289 :
290 : // Creates a visitor for all compilands of @p session.
291 m : explicit CompilandVisitor(IDiaSession* session);
292 :
293 : // Visits all compilands, calling @p compiland_callback for each.
294 : // @returns true on success.
295 m : bool VisitAllCompilands(const VisitCompilandCallback& compiland_callback);
296 :
297 m : private:
298 m : base::win::ScopedComPtr<IDiaSession> session_;
299 :
300 m : DISALLOW_COPY_AND_ASSIGN(CompilandVisitor);
301 m : };
302 :
303 : // A worker class that makes it easy to visit each source line record
304 : // in a given DIA compiland.
305 m : class LineVisitor {
306 m : public:
307 m : typedef base::Callback<bool(IDiaLineNumber*)> VisitLineCallback;
308 :
309 : // Create a line visitor for the given @p session and @p compiland.
310 m : LineVisitor(IDiaSession* session, IDiaSymbol* compiland);
311 :
312 : // Visit all lines records in our compiland.
313 m : bool VisitLines(const VisitLineCallback& line_callback);
314 :
315 m : private:
316 m : bool VisitLinesImpl();
317 m : bool EnumerateCompilandSource(IDiaSymbol* compiland,
318 m : IDiaSourceFile* source_file);
319 m : bool EnumerateCompilandSources(IDiaSymbol* compiland,
320 m : IDiaEnumSourceFiles* source_files);
321 m : bool VisitSourceLine(IDiaLineNumber* line_number);
322 :
323 m : base::win::ScopedComPtr<IDiaSession> session_;
324 m : base::win::ScopedComPtr<IDiaSymbol> compiland_;
325 :
326 m : const VisitLineCallback* line_callback_;
327 :
328 m : DISALLOW_COPY_AND_ASSIGN(LineVisitor);
329 m : };
330 :
331 : // This macro allows the easy construction of switch statements over the
332 : // SymTagEnum.
333 : #define SYMTAG_CASE_TABLE(decl) \
334 m : decl(SymTagNull) \
335 m : decl(SymTagExe) \
336 m : decl(SymTagCompiland) \
337 m : decl(SymTagCompilandDetails) \
338 m : decl(SymTagCompilandEnv) \
339 m : decl(SymTagFunction) \
340 m : decl(SymTagBlock) \
341 m : decl(SymTagData) \
342 m : decl(SymTagAnnotation) \
343 m : decl(SymTagLabel) \
344 m : decl(SymTagPublicSymbol) \
345 m : decl(SymTagUDT) \
346 m : decl(SymTagEnum) \
347 m : decl(SymTagFunctionType) \
348 m : decl(SymTagPointerType) \
349 m : decl(SymTagArrayType) \
350 m : decl(SymTagBaseType) \
351 m : decl(SymTagTypedef) \
352 m : decl(SymTagBaseClass) \
353 m : decl(SymTagFriend) \
354 m : decl(SymTagFunctionArgType) \
355 m : decl(SymTagFuncDebugStart) \
356 m : decl(SymTagFuncDebugEnd) \
357 m : decl(SymTagUsingNamespace) \
358 m : decl(SymTagVTableShape) \
359 m : decl(SymTagVTable) \
360 m : decl(SymTagCustom) \
361 m : decl(SymTagThunk) \
362 m : decl(SymTagCustomType) \
363 m : decl(SymTagManagedType) \
364 m : decl(SymTagDimension) \
365 m : decl(SymTagCallSite) \
366 m : decl(SymTagInlineSite) \
367 m : decl(SymTagBaseInterface) \
368 m : decl(SymTagVectorType) \
369 m : decl(SymTagMatrixType) \
370 m : decl(SymTagHLSLType)
371 :
372 m : } // namespace pe
373 :
374 : // Bring in the templated implementation details.
375 : #include "syzygy/pe/dia_util_internal.h"
376 :
377 : #endif // SYZYGY_PE_DIA_UTIL_H_
|