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 : // Creates a DiaDataSource object. Logs any errors.
49 : //
50 : // @param created_source pointer that will receive the created object.
51 : // @returns true on success, false otherwise.
52 m : bool CreateDiaSource(IDiaDataSource** created_source);
53 :
54 : // Creates a dia session for the provided object. Logs any errors.
55 : //
56 : // @param file the file to open.
57 : // @param dia_source the DIA source to use.
58 : // @param dia_session pointer that will receive the created DIA session.
59 : // @returns true on success, false otherwise.
60 m : bool CreateDiaSession(const base::FilePath& file,
61 m : IDiaDataSource* dia_source,
62 m : IDiaSession** dia_session);
63 :
64 : // Find the table with the given IID. Logs any errors.
65 : //
66 : // @param iid the IID of the table to look for.
67 : // @param dia_session the DIA session whose tables are to be queried.
68 : // @param out_table a pointer to the object to receive the table. If the table
69 : // is not found this will be NULL on return.
70 : // @returns a SearchResult
71 m : SearchResult FindDiaTable(const IID& iid,
72 m : IDiaSession* dia_session,
73 m : void** out_table);
74 :
75 : // Find the table that can be cast to the given Dia interface. Logs any errors.
76 : //
77 : // @tparam T an IDia* intercace.
78 : // @param session the DIA session whose tables are to be queried.
79 : // @param out_table a pointer to the object to receive the table. If the table
80 : // is not found this will be NULL on return.
81 : // @returns a SearchResult
82 m : template <typename T>
83 m : SearchResult FindDiaTable(IDiaSession* dia_session, T** out_table);
84 :
85 : // Finds teh debug stream with the given name. Logs any errors.
86 : //
87 : // @param name the name of the stream to find.
88 : // @param dia_session the DIA session to search.
89 : // @param dia_debug_stream the pointer that will receive the debug stream, if
90 : // found.
91 : // @returns a SearchResult.
92 m : SearchResult FindDiaDebugStream(const wchar_t* name,
93 m : IDiaSession* dia_session,
94 m : IDiaEnumDebugStreamData** dia_debug_stream);
95 :
96 : // This reads a given debug stream into the provided vector. The type T
97 : // must be the same size as the debug stream record size. Logs any errors.
98 : //
99 : // @tparam T the type of object to read from the debug stream.
100 : // @param stream the debug stream from which to read objects.
101 : // @param list the list to be populated.
102 : // @returns true on success, false otherwise.
103 m : template <typename T>
104 m : bool LoadDiaDebugStream(IDiaEnumDebugStreamData* stream, std::vector<T>* list);
105 :
106 : // This loads the named debug stream into the provided vector. The type T must
107 : // be the same size as the debug stream record size. Logs any errors.
108 : //
109 : // @tparam T the type of object to read from the debug stream.
110 : // @param name the name of the stream to load.
111 : // @param dia_session the DIA session to search.
112 : // @param list the list to be populated.
113 : // @returns a SearchResults.
114 m : template <typename T>
115 m : SearchResult FindAndLoadDiaDebugStreamByName(const wchar_t* name,
116 m : IDiaSession* dia_session,
117 m : std::vector<T>* list);
118 :
119 : // Gets the index id associated with the given symbol.
120 : // @param symbol the symbol to examine.
121 : // @param sym_index_id on success, returns @p symbol's index id.
122 : // @returns true on success, false on failure.
123 m : bool GetSymIndexId(IDiaSymbol* symbol, uint32_t* sym_index_id);
124 :
125 : // Gets the symbol tab associated with the given symbol.
126 : // @param symbol the symbol to examine.
127 : // @param sym_tag on success, returns @p symbol's tag.
128 : // @returns true on success, false on failure.
129 m : bool GetSymTag(IDiaSymbol* symbol, enum SymTagEnum* sym_tag);
130 :
131 : // Checks to see if the given symbol is of the expected type.
132 : // @returns true if @p symbol is of type @p expected_sym_tag,
133 : // false on error or mismatch.
134 m : bool IsSymTag(IDiaSymbol* symbol, enum SymTagEnum expected_sym_tag);
135 :
136 : // Gets the name associated with the given symbol.
137 : // @param symbol the symbol to examine.
138 : // @param name on success, returns @p symbol's name.
139 : // @returns true on success, false on failure.
140 m : bool GetSymName(IDiaSymbol* symbol, base::string16* name);
141 :
142 : // Gets the undecorated name associated with the given symbol.
143 : // @param symbol the symbol to examine.
144 : // @param name on success, returns @p symbol's undecorated name.
145 : // @returns true on success, false on failure.
146 m : bool GetSymUndecoratedName(IDiaSymbol* symbol, base::string16* name);
147 :
148 : // Gets the symbol's data kind.
149 : // @param symbol the symbol to examine.
150 : // @param kind on success, returns @p symbol's data kind.
151 : // @returns true on success, false on failure.
152 m : bool GetDataKind(IDiaSymbol* symbol, enum DataKind* kind);
153 :
154 : // Gets the symbol's location type.
155 : // @param symbol the symbol to examine.
156 : // @param location_type on success, returns @p symbol's location type.
157 : // @returns true on success, false on failure.
158 m : bool GetLocationType(IDiaSymbol* symbol, enum LocationType* location_type);
159 :
160 : // Gets the symbol's register id.
161 : // @param symbol the symbol to examine.
162 : // @param register_id on success, returns @p symbol's register id.
163 : // @returns true on success, false on failure.
164 m : bool GetRegisterId(IDiaSymbol* symbol, uint32_t* register_id);
165 :
166 : // Gets the symbol's offset.
167 : // @param symbol the symbol to examine.
168 : // @param offset on success, returns @p symbol's offset.
169 : // @returns true on success, false on failure.
170 m : bool GetSymOffset(IDiaSymbol* symbol, ptrdiff_t* offset);
171 :
172 : // Gets the symbol's type.
173 : // @param symbol the symbol to examine.
174 : // @param type on success, returns @p symbol's type.
175 : // @returns true on success, false on failure.
176 m : bool GetSymType(IDiaSymbol* symbol, base::win::ScopedComPtr<IDiaSymbol>* type);
177 :
178 : // Gets the symbol's CV qualifiers.
179 : // @param symbol the symbol to examine.
180 : // @param is_const on success, returns whether @p symbol is const qualified.
181 : // @param is_volatile on success, returns whether @p symbol is volatile
182 : // qualified.
183 : // @returns true on success, false on failure.
184 m : bool GetSymQualifiers(IDiaSymbol* symbol, bool* is_const, bool* is_volatile);
185 :
186 : // Gets the number of items contained by the type.
187 : // @param symbol the symbol to examine.
188 : // @param count on success, returns the number of items.
189 : // @returns true on success, false on failure.
190 m : bool GetSymCount(IDiaSymbol* symbol, size_t* count);
191 :
192 : // Gets the symbol's class parent.
193 : // @param symbol the symbol to examine.
194 : // @param parent on success, returns @p symbol's class parent or nullptr if the
195 : // parent property is no available for the symbol.
196 : // @returns true on success, false on failure.
197 m : bool GetSymClassParent(IDiaSymbol* symbol,
198 m : base::win::ScopedComPtr<IDiaSymbol>* parent);
199 :
200 : // Gets the symbol's lexical parent.
201 : // @param symbol the symbol to examine.
202 : // @param parent on success, returns @p symbol's lexical parent.
203 : // @returns true on success, false on failure.
204 m : bool GetSymLexicalParent(IDiaSymbol* symbol,
205 m : base::win::ScopedComPtr<IDiaSymbol>* parent);
206 :
207 : // Gets the frame's base address.
208 : // @param frame the stack frame.
209 : // @param frame_base on success, returns @p frame's base address.
210 : // @returns true on sucess, false on failure.
211 m : bool GetFrameBase(IDiaStackFrame* frame, uint64_t* frame_base);
212 :
213 : // Gets a register's value for the frame.
214 : // @param frame the stack frame.
215 : // @param register_index the index of the desired register.
216 : // @param frame_base on success, returns the register's value.
217 : // @returns true on sucess, false on failure.
218 m : bool GetRegisterValue(IDiaStackFrame* frame,
219 m : CV_HREG_e register_index,
220 m : uint64_t* register_value);
221 :
222 : // Gets the stack frame's size.
223 : // @param frame the stack frame.
224 : // @param frame_size on success, returns @p frame's size.
225 : // @returns true on sucess, false on failure.
226 m : bool GetSize(IDiaStackFrame* frame, uint32_t* frame_size);
227 :
228 : // Gets the stack frame's locals base address.
229 : // @param frame the stack frame.
230 : // @param size on success, returns the base address of the locals.
231 : // @returns true on sucess, false on failure.
232 m : bool GetLocalsBase(IDiaStackFrame* frame, uint64_t* locals_base);
233 :
234 : // A worker class that makes it easy to visit specific children of a given
235 : // DIA symbol.
236 m : class ChildVisitor {
237 m : public:
238 m : typedef base::Callback<bool(IDiaSymbol*)> VisitSymbolCallback;
239 :
240 : // Creates a visitor for the children of @p parent of type @p type.
241 m : ChildVisitor(IDiaSymbol* parent, enum SymTagEnum type);
242 :
243 : // Visits all children of type type, of parent symbol,
244 : // calling @p child_callback for each.
245 : // @returns true on success.
246 m : bool VisitChildren(const VisitSymbolCallback& child_callback);
247 :
248 m : private:
249 m : bool VisitChildrenImpl();
250 m : bool EnumerateChildren(IDiaEnumSymbols* children);
251 m : bool VisitChild(IDiaSymbol* child);
252 :
253 m : base::win::ScopedComPtr<IDiaSymbol> parent_;
254 m : enum SymTagEnum type_;
255 :
256 m : const VisitSymbolCallback* child_callback_;
257 :
258 m : DISALLOW_COPY_AND_ASSIGN(ChildVisitor);
259 m : };
260 :
261 : // A worker class that makes it easy to visit each compiland in
262 : // in a given DIA session.
263 m : class CompilandVisitor {
264 m : public:
265 m : typedef ChildVisitor::VisitSymbolCallback VisitCompilandCallback;
266 :
267 : // Creates a visitor for all compilands of @p session.
268 m : explicit CompilandVisitor(IDiaSession* session);
269 :
270 : // Visits all compilands, calling @p compiland_callback for each.
271 : // @returns true on success.
272 m : bool VisitAllCompilands(const VisitCompilandCallback& compiland_callback);
273 :
274 m : private:
275 m : base::win::ScopedComPtr<IDiaSession> session_;
276 :
277 m : DISALLOW_COPY_AND_ASSIGN(CompilandVisitor);
278 m : };
279 :
280 : // A worker class that makes it easy to visit each source line record
281 : // in a given DIA compiland.
282 m : class LineVisitor {
283 m : public:
284 m : typedef base::Callback<bool(IDiaLineNumber*)> VisitLineCallback;
285 :
286 : // Create a line visitor for the given @p session and @p compiland.
287 m : LineVisitor(IDiaSession* session, IDiaSymbol* compiland);
288 :
289 : // Visit all lines records in our compiland.
290 m : bool VisitLines(const VisitLineCallback& line_callback);
291 :
292 m : private:
293 m : bool VisitLinesImpl();
294 m : bool EnumerateCompilandSource(IDiaSymbol* compiland,
295 m : IDiaSourceFile* source_file);
296 m : bool EnumerateCompilandSources(IDiaSymbol* compiland,
297 m : IDiaEnumSourceFiles* source_files);
298 m : bool VisitSourceLine(IDiaLineNumber* line_number);
299 :
300 m : base::win::ScopedComPtr<IDiaSession> session_;
301 m : base::win::ScopedComPtr<IDiaSymbol> compiland_;
302 :
303 m : const VisitLineCallback* line_callback_;
304 :
305 m : DISALLOW_COPY_AND_ASSIGN(LineVisitor);
306 m : };
307 :
308 : // This macro allows the easy construction of switch statements over the
309 : // SymTagEnum.
310 : #define SYMTAG_CASE_TABLE(decl) \
311 m : decl(SymTagNull) \
312 m : decl(SymTagExe) \
313 m : decl(SymTagCompiland) \
314 m : decl(SymTagCompilandDetails) \
315 m : decl(SymTagCompilandEnv) \
316 m : decl(SymTagFunction) \
317 m : decl(SymTagBlock) \
318 m : decl(SymTagData) \
319 m : decl(SymTagAnnotation) \
320 m : decl(SymTagLabel) \
321 m : decl(SymTagPublicSymbol) \
322 m : decl(SymTagUDT) \
323 m : decl(SymTagEnum) \
324 m : decl(SymTagFunctionType) \
325 m : decl(SymTagPointerType) \
326 m : decl(SymTagArrayType) \
327 m : decl(SymTagBaseType) \
328 m : decl(SymTagTypedef) \
329 m : decl(SymTagBaseClass) \
330 m : decl(SymTagFriend) \
331 m : decl(SymTagFunctionArgType) \
332 m : decl(SymTagFuncDebugStart) \
333 m : decl(SymTagFuncDebugEnd) \
334 m : decl(SymTagUsingNamespace) \
335 m : decl(SymTagVTableShape) \
336 m : decl(SymTagVTable) \
337 m : decl(SymTagCustom) \
338 m : decl(SymTagThunk) \
339 m : decl(SymTagCustomType) \
340 m : decl(SymTagManagedType) \
341 m : decl(SymTagDimension) \
342 m : decl(SymTagCallSite) \
343 m : decl(SymTagInlineSite) \
344 m : decl(SymTagBaseInterface) \
345 m : decl(SymTagVectorType) \
346 m : decl(SymTagMatrixType) \
347 m : decl(SymTagHLSLType)
348 :
349 m : } // namespace pe
350 :
351 : // Bring in the templated implementation details.
352 : #include "syzygy/pe/dia_util_internal.h"
353 :
354 : #endif // SYZYGY_PE_DIA_UTIL_H_
|