OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006, Google Inc. | |
2 // All rights reserved. | |
3 // | |
4 // Redistribution and use in source and binary forms, with or without | |
5 // modification, are permitted provided that the following conditions are | |
6 // met: | |
7 // | |
8 // * Redistributions of source code must retain the above copyright | |
9 // notice, this list of conditions and the following disclaimer. | |
10 // * Redistributions in binary form must reproduce the above | |
11 // copyright notice, this list of conditions and the following disclaimer | |
12 // in the documentation and/or other materials provided with the | |
13 // distribution. | |
14 // * Neither the name of Google Inc. nor the names of its | |
15 // contributors may be used to endorse or promote products derived from | |
16 // this software without specific prior written permission. | |
17 // | |
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 #include <atlbase.h> | |
31 #include <DbgHelp.h> | |
32 #include <dia2.h> | |
33 #include <stdio.h> | |
34 | |
35 #include "common/windows/string_utils-inl.h" | |
36 | |
37 #include "common/windows/pdb_source_line_writer.h" | |
38 #include "common/windows/guid_string.h" | |
39 | |
40 // This constant may be missing from DbgHelp.h. See the documentation for | |
41 // IDiaSymbol::get_undecoratedNameEx. | |
42 #ifndef UNDNAME_NO_ECSU | |
43 #define UNDNAME_NO_ECSU 0x8000 // Suppresses enum/class/struct/union. | |
44 #endif // UNDNAME_NO_ECSU | |
45 | |
46 namespace google_breakpad { | |
47 | |
48 PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) { | |
49 } | |
50 | |
51 PDBSourceLineWriter::~PDBSourceLineWriter() { | |
52 } | |
53 | |
54 bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) { | |
55 Close(); | |
56 | |
57 if (FAILED(CoInitialize(NULL))) { | |
58 fprintf(stderr, "CoInitialize failed\n"); | |
59 return false; | |
60 } | |
61 | |
62 CComPtr<IDiaDataSource> data_source; | |
63 if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) { | |
64 fprintf(stderr, "CoCreateInstance CLSID_DiaSource failed " | |
65 "(msdia80.dll unregistered?)\n"); | |
66 return false; | |
67 } | |
68 | |
69 switch (format) { | |
70 case PDB_FILE: | |
71 if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { | |
72 fprintf(stderr, "loadDataFromPdb failed\n"); | |
73 return false; | |
74 } | |
75 break; | |
76 case EXE_FILE: | |
77 if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { | |
78 fprintf(stderr, "loadDataForExe failed\n"); | |
79 return false; | |
80 } | |
81 break; | |
82 case ANY_FILE: | |
83 if (FAILED(data_source->loadDataFromPdb(file.c_str()))) { | |
84 if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) { | |
85 fprintf(stderr, "loadDataForPdb and loadDataFromExe failed\n"); | |
86 return false; | |
87 } | |
88 } | |
89 break; | |
90 default: | |
91 fprintf(stderr, "Unknown file format\n"); | |
92 return false; | |
93 } | |
94 | |
95 if (FAILED(data_source->openSession(&session_))) { | |
96 fprintf(stderr, "openSession failed\n"); | |
97 } | |
98 | |
99 return true; | |
100 } | |
101 | |
102 bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) { | |
103 // The line number format is: | |
104 // <rva> <line number> <source file id> | |
105 CComPtr<IDiaLineNumber> line; | |
106 ULONG count; | |
107 | |
108 while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) { | |
109 DWORD rva; | |
110 if (FAILED(line->get_relativeVirtualAddress(&rva))) { | |
111 fprintf(stderr, "failed to get line rva\n"); | |
112 return false; | |
113 } | |
114 | |
115 DWORD length; | |
116 if (FAILED(line->get_length(&length))) { | |
117 fprintf(stderr, "failed to get line code length\n"); | |
118 return false; | |
119 } | |
120 | |
121 DWORD dia_source_id; | |
122 if (FAILED(line->get_sourceFileId(&dia_source_id))) { | |
123 fprintf(stderr, "failed to get line source file id\n"); | |
124 return false; | |
125 } | |
126 // duplicate file names are coalesced to share one ID | |
127 DWORD source_id = GetRealFileID(dia_source_id); | |
128 | |
129 DWORD line_num; | |
130 if (FAILED(line->get_lineNumber(&line_num))) { | |
131 fprintf(stderr, "failed to get line number\n"); | |
132 return false; | |
133 } | |
134 | |
135 fprintf(output_, "%x %x %d %d\n", rva, length, line_num, source_id); | |
136 line.Release(); | |
137 } | |
138 return true; | |
139 } | |
140 | |
141 bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function, | |
142 IDiaSymbol *block) { | |
143 // The function format is: | |
144 // FUNC <address> <length> <param_stack_size> <function> | |
145 DWORD rva; | |
146 if (FAILED(block->get_relativeVirtualAddress(&rva))) { | |
147 fprintf(stderr, "couldn't get rva\n"); | |
148 return false; | |
149 } | |
150 | |
151 ULONGLONG length; | |
152 if (FAILED(block->get_length(&length))) { | |
153 fprintf(stderr, "failed to get function length\n"); | |
154 return false; | |
155 } | |
156 | |
157 if (length == 0) { | |
158 // Silently ignore zero-length functions, which can infrequently pop up. | |
159 return true; | |
160 } | |
161 | |
162 CComBSTR name; | |
163 int stack_param_size; | |
164 if (!GetSymbolFunctionName(function, &name, &stack_param_size)) { | |
165 return false; | |
166 } | |
167 | |
168 // If the decorated name didn't give the parameter size, try to | |
169 // calculate it. | |
170 if (stack_param_size < 0) { | |
171 stack_param_size = GetFunctionStackParamSize(function); | |
172 } | |
173 | |
174 fprintf(output_, "FUNC %x %" WIN_STRING_FORMAT_LL "x %x %ws\n", | |
175 rva, length, stack_param_size, name); | |
176 | |
177 CComPtr<IDiaEnumLineNumbers> lines; | |
178 if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) { | |
179 return false; | |
180 } | |
181 | |
182 if (!PrintLines(lines)) { | |
183 return false; | |
184 } | |
185 return true; | |
186 } | |
187 | |
188 bool PDBSourceLineWriter::PrintSourceFiles() { | |
189 CComPtr<IDiaSymbol> global; | |
190 if (FAILED(session_->get_globalScope(&global))) { | |
191 fprintf(stderr, "get_globalScope failed\n"); | |
192 return false; | |
193 } | |
194 | |
195 CComPtr<IDiaEnumSymbols> compilands; | |
196 if (FAILED(global->findChildren(SymTagCompiland, NULL, | |
197 nsNone, &compilands))) { | |
198 fprintf(stderr, "findChildren failed\n"); | |
199 return false; | |
200 } | |
201 | |
202 CComPtr<IDiaSymbol> compiland; | |
203 ULONG count; | |
204 while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { | |
205 CComPtr<IDiaEnumSourceFiles> source_files; | |
206 if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) { | |
207 return false; | |
208 } | |
209 CComPtr<IDiaSourceFile> file; | |
210 while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) { | |
211 DWORD file_id; | |
212 if (FAILED(file->get_uniqueId(&file_id))) { | |
213 return false; | |
214 } | |
215 | |
216 CComBSTR file_name; | |
217 if (FAILED(file->get_fileName(&file_name))) { | |
218 return false; | |
219 } | |
220 | |
221 wstring file_name_string(file_name); | |
222 if (!FileIDIsCached(file_name_string)) { | |
223 // this is a new file name, cache it and output a FILE line. | |
224 CacheFileID(file_name_string, file_id); | |
225 fwprintf(output_, L"FILE %d %s\n", file_id, file_name); | |
226 } else { | |
227 // this file name has already been seen, just save this | |
228 // ID for later lookup. | |
229 StoreDuplicateFileID(file_name_string, file_id); | |
230 } | |
231 file.Release(); | |
232 } | |
233 compiland.Release(); | |
234 } | |
235 return true; | |
236 } | |
237 | |
238 bool PDBSourceLineWriter::PrintFunctions() { | |
239 CComPtr<IDiaEnumSymbolsByAddr> symbols; | |
240 if (FAILED(session_->getSymbolsByAddr(&symbols))) { | |
241 fprintf(stderr, "failed to get symbol enumerator\n"); | |
242 return false; | |
243 } | |
244 | |
245 CComPtr<IDiaSymbol> symbol; | |
246 if (FAILED(symbols->symbolByAddr(1, 0, &symbol))) { | |
247 fprintf(stderr, "failed to enumerate symbols\n"); | |
248 return false; | |
249 } | |
250 | |
251 DWORD rva_last = 0; | |
252 if (FAILED(symbol->get_relativeVirtualAddress(&rva_last))) { | |
253 fprintf(stderr, "failed to get symbol rva\n"); | |
254 return false; | |
255 } | |
256 | |
257 ULONG count; | |
258 do { | |
259 DWORD tag; | |
260 if (FAILED(symbol->get_symTag(&tag))) { | |
261 fprintf(stderr, "failed to get symbol tag\n"); | |
262 return false; | |
263 } | |
264 | |
265 // For a given function, DIA seems to give either a symbol with | |
266 // SymTagFunction or SymTagPublicSymbol, but not both. This means | |
267 // that PDBSourceLineWriter will output either a FUNC or PUBLIC line, | |
268 // but not both. | |
269 if (tag == SymTagFunction) { | |
270 if (!PrintFunction(symbol, symbol)) { | |
271 return false; | |
272 } | |
273 } else if (tag == SymTagPublicSymbol) { | |
274 if (!PrintCodePublicSymbol(symbol)) { | |
275 return false; | |
276 } | |
277 } | |
278 symbol.Release(); | |
279 } while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1); | |
280 | |
281 // When building with PGO, the compiler can split functions into | |
282 // "hot" and "cold" blocks, and move the "cold" blocks out to separate | |
283 // pages, so the function can be noncontiguous. To find these blocks, | |
284 // we have to iterate over all the compilands, and then find blocks | |
285 // that are children of them. We can then find the lexical parents | |
286 // of those blocks and print out an extra FUNC line for blocks | |
287 // that are not contained in their parent functions. | |
288 CComPtr<IDiaSymbol> global; | |
289 if (FAILED(session_->get_globalScope(&global))) { | |
290 fprintf(stderr, "get_globalScope failed\n"); | |
291 return false; | |
292 } | |
293 | |
294 CComPtr<IDiaEnumSymbols> compilands; | |
295 if (FAILED(global->findChildren(SymTagCompiland, NULL, | |
296 nsNone, &compilands))) { | |
297 fprintf(stderr, "findChildren failed on the global\n"); | |
298 return false; | |
299 } | |
300 | |
301 CComPtr<IDiaSymbol> compiland; | |
302 while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { | |
303 CComPtr<IDiaEnumSymbols> blocks; | |
304 if (FAILED(compiland->findChildren(SymTagBlock, NULL, | |
305 nsNone, &blocks))) { | |
306 fprintf(stderr, "findChildren failed on a compiland\n"); | |
307 return false; | |
308 } | |
309 | |
310 CComPtr<IDiaSymbol> block; | |
311 while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) { | |
312 // find this block's lexical parent function | |
313 CComPtr<IDiaSymbol> parent; | |
314 DWORD tag; | |
315 if (SUCCEEDED(block->get_lexicalParent(&parent)) && | |
316 SUCCEEDED(parent->get_symTag(&tag)) && | |
317 tag == SymTagFunction) { | |
318 // now get the block's offset and the function's offset and size, | |
319 // and determine if the block is outside of the function | |
320 DWORD func_rva, block_rva; | |
321 ULONGLONG func_length; | |
322 if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) && | |
323 SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) && | |
324 SUCCEEDED(parent->get_length(&func_length))) { | |
325 if (block_rva < func_rva || block_rva > (func_rva + func_length)) { | |
326 if (!PrintFunction(parent, block)) { | |
327 return false; | |
328 } | |
329 } | |
330 } | |
331 } | |
332 parent.Release(); | |
333 block.Release(); | |
334 } | |
335 blocks.Release(); | |
336 compiland.Release(); | |
337 } | |
338 | |
339 return true; | |
340 } | |
341 | |
342 bool PDBSourceLineWriter::PrintFrameData() { | |
343 // It would be nice if it were possible to output frame data alongside the | |
344 // associated function, as is done with line numbers, but the DIA API | |
345 // doesn't make it possible to get the frame data in that way. | |
346 | |
347 CComPtr<IDiaEnumTables> tables; | |
348 if (FAILED(session_->getEnumTables(&tables))) | |
349 return false; | |
350 | |
351 // Pick up the first table that supports IDiaEnumFrameData. | |
352 CComPtr<IDiaEnumFrameData> frame_data_enum; | |
353 CComPtr<IDiaTable> table; | |
354 ULONG count; | |
355 while (!frame_data_enum && | |
356 SUCCEEDED(tables->Next(1, &table, &count)) && | |
357 count == 1) { | |
358 table->QueryInterface(_uuidof(IDiaEnumFrameData), | |
359 reinterpret_cast<void**>(&frame_data_enum)); | |
360 table.Release(); | |
361 } | |
362 if (!frame_data_enum) | |
363 return false; | |
364 | |
365 DWORD last_type = -1; | |
366 DWORD last_rva = -1; | |
367 DWORD last_code_size = 0; | |
368 DWORD last_prolog_size = -1; | |
369 | |
370 CComPtr<IDiaFrameData> frame_data; | |
371 while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) && | |
372 count == 1) { | |
373 DWORD type; | |
374 if (FAILED(frame_data->get_type(&type))) | |
375 return false; | |
376 | |
377 DWORD rva; | |
378 if (FAILED(frame_data->get_relativeVirtualAddress(&rva))) | |
379 return false; | |
380 | |
381 DWORD code_size; | |
382 if (FAILED(frame_data->get_lengthBlock(&code_size))) | |
383 return false; | |
384 | |
385 DWORD prolog_size; | |
386 if (FAILED(frame_data->get_lengthProlog(&prolog_size))) | |
387 return false; | |
388 | |
389 // epliog_size is always 0. | |
390 DWORD epilog_size = 0; | |
391 | |
392 // parameter_size is the size of parameters passed on the stack. If any | |
393 // parameters are not passed on the stack (such as in registers), their | |
394 // sizes will not be included in parameter_size. | |
395 DWORD parameter_size; | |
396 if (FAILED(frame_data->get_lengthParams(¶meter_size))) | |
397 return false; | |
398 | |
399 DWORD saved_register_size; | |
400 if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size))) | |
401 return false; | |
402 | |
403 DWORD local_size; | |
404 if (FAILED(frame_data->get_lengthLocals(&local_size))) | |
405 return false; | |
406 | |
407 // get_maxStack can return S_FALSE, just use 0 in that case. | |
408 DWORD max_stack_size = 0; | |
409 if (FAILED(frame_data->get_maxStack(&max_stack_size))) | |
410 return false; | |
411 | |
412 // get_programString can return S_FALSE, indicating that there is no | |
413 // program string. In that case, check whether %ebp is used. | |
414 HRESULT program_string_result; | |
415 CComBSTR program_string; | |
416 if (FAILED(program_string_result = frame_data->get_program( | |
417 &program_string))) { | |
418 return false; | |
419 } | |
420 | |
421 // get_allocatesBasePointer can return S_FALSE, treat that as though | |
422 // %ebp is not used. | |
423 BOOL allocates_base_pointer = FALSE; | |
424 if (program_string_result != S_OK) { | |
425 if (FAILED(frame_data->get_allocatesBasePointer( | |
426 &allocates_base_pointer))) { | |
427 return false; | |
428 } | |
429 } | |
430 | |
431 // Only print out a line if type, rva, code_size, or prolog_size have | |
432 // changed from the last line. It is surprisingly common (especially in | |
433 // system library PDBs) for DIA to return a series of identical | |
434 // IDiaFrameData objects. For kernel32.pdb from Windows XP SP2 on x86, | |
435 // this check reduces the size of the dumped symbol file by a third. | |
436 if (type != last_type || rva != last_rva || code_size != last_code_size || | |
437 prolog_size != last_prolog_size) { | |
438 fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ", | |
439 type, rva, code_size, prolog_size, epilog_size, | |
440 parameter_size, saved_register_size, local_size, max_stack_size, | |
441 program_string_result == S_OK); | |
442 if (program_string_result == S_OK) { | |
443 fprintf(output_, "%ws\n", program_string); | |
444 } else { | |
445 fprintf(output_, "%d\n", allocates_base_pointer); | |
446 } | |
447 | |
448 last_type = type; | |
449 last_rva = rva; | |
450 last_code_size = code_size; | |
451 last_prolog_size = prolog_size; | |
452 } | |
453 | |
454 frame_data.Release(); | |
455 } | |
456 | |
457 return true; | |
458 } | |
459 | |
460 bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) { | |
461 BOOL is_code; | |
462 if (FAILED(symbol->get_code(&is_code))) { | |
463 return false; | |
464 } | |
465 if (!is_code) { | |
466 return true; | |
467 } | |
468 | |
469 DWORD rva; | |
470 if (FAILED(symbol->get_relativeVirtualAddress(&rva))) { | |
471 return false; | |
472 } | |
473 | |
474 CComBSTR name; | |
475 int stack_param_size; | |
476 if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) { | |
477 return false; | |
478 } | |
479 | |
480 fprintf(output_, "PUBLIC %x %x %ws\n", rva, | |
481 stack_param_size > 0 ? stack_param_size : 0, name); | |
482 return true; | |
483 } | |
484 | |
485 bool PDBSourceLineWriter::PrintPDBInfo() { | |
486 PDBModuleInfo info; | |
487 if (!GetModuleInfo(&info)) { | |
488 return false; | |
489 } | |
490 | |
491 // Hard-code "windows" for the OS because that's the only thing that makes | |
492 // sense for PDB files. (This might not be strictly correct for Windows CE | |
493 // support, but we don't care about that at the moment.) | |
494 fprintf(output_, "MODULE windows %ws %ws %ws\n", | |
495 info.cpu.c_str(), info.debug_identifier.c_str(), | |
496 info.debug_file.c_str()); | |
497 | |
498 return true; | |
499 } | |
500 | |
501 // wcstol_positive_strict is sort of like wcstol, but much stricter. string | |
502 // should be a buffer pointing to a null-terminated string containing only | |
503 // decimal digits. If the entire string can be converted to an integer | |
504 // without overflowing, and there are no non-digit characters before the | |
505 // result is set to the value and this function returns true. Otherwise, | |
506 // this function returns false. This is an alternative to the strtol, atoi, | |
507 // and scanf families, which are not as strict about input and in some cases | |
508 // don't provide a good way for the caller to determine if a conversion was | |
509 // successful. | |
510 static bool wcstol_positive_strict(wchar_t *string, int *result) { | |
511 int value = 0; | |
512 for (wchar_t *c = string; *c != '\0'; ++c) { | |
513 int last_value = value; | |
514 value *= 10; | |
515 // Detect overflow. | |
516 if (value / 10 != last_value || value < 0) { | |
517 return false; | |
518 } | |
519 if (*c < '0' || *c > '9') { | |
520 return false; | |
521 } | |
522 unsigned int c_value = *c - '0'; | |
523 last_value = value; | |
524 value += c_value; | |
525 // Detect overflow. | |
526 if (value < last_value) { | |
527 return false; | |
528 } | |
529 // Forbid leading zeroes unless the string is just "0". | |
530 if (value == 0 && *(c+1) != '\0') { | |
531 return false; | |
532 } | |
533 } | |
534 *result = value; | |
535 return true; | |
536 } | |
537 | |
538 // static | |
539 bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function, | |
540 BSTR *name, | |
541 int *stack_param_size) { | |
542 *stack_param_size = -1; | |
543 const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS | | |
544 UNDNAME_NO_FUNCTION_RETURNS | | |
545 UNDNAME_NO_ALLOCATION_MODEL | | |
546 UNDNAME_NO_ALLOCATION_LANGUAGE | | |
547 UNDNAME_NO_THISTYPE | | |
548 UNDNAME_NO_ACCESS_SPECIFIERS | | |
549 UNDNAME_NO_THROW_SIGNATURES | | |
550 UNDNAME_NO_MEMBER_TYPE | | |
551 UNDNAME_NO_RETURN_UDT_MODEL | | |
552 UNDNAME_NO_ECSU; | |
553 | |
554 // Use get_undecoratedNameEx to get readable C++ names with arguments. | |
555 if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) { | |
556 if (function->get_name(name) != S_OK) { | |
557 fprintf(stderr, "failed to get function name\n"); | |
558 return false; | |
559 } | |
560 // If a name comes from get_name because no undecorated form existed, | |
561 // it's already formatted properly to be used as output. Don't do any | |
562 // additional processing. | |
563 // | |
564 // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's. | |
565 // This will result in calling get_name for some C++ symbols, so | |
566 // all of the parameter and return type information may not be included in | |
567 // the name string. | |
568 } else { | |
569 // C++ uses a bogus "void" argument for functions and methods that don't | |
570 // take any parameters. Take it out of the undecorated name because it's | |
571 // ugly and unnecessary. | |
572 const wchar_t *replace_string = L"(void)"; | |
573 const size_t replace_length = wcslen(replace_string); | |
574 const wchar_t *replacement_string = L"()"; | |
575 size_t length = wcslen(*name); | |
576 if (length >= replace_length) { | |
577 wchar_t *name_end = *name + length - replace_length; | |
578 if (wcscmp(name_end, replace_string) == 0) { | |
579 WindowsStringUtils::safe_wcscpy(name_end, replace_length, | |
580 replacement_string); | |
581 length = wcslen(*name); | |
582 } | |
583 } | |
584 | |
585 // Undecorate names used for stdcall and fastcall. These names prefix | |
586 // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it | |
587 // with '@' followed by the number of bytes of parameters, in decimal. | |
588 // If such a name is found, take note of the size and undecorate it. | |
589 // Only do this for names that aren't C++, which is determined based on | |
590 // whether the undecorated name contains any ':' or '(' characters. | |
591 if (!wcschr(*name, ':') && !wcschr(*name, '(') && | |
592 (*name[0] == '_' || *name[0] == '@')) { | |
593 wchar_t *last_at = wcsrchr(*name + 1, '@'); | |
594 if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) { | |
595 // If this function adheres to the fastcall convention, it accepts up | |
596 // to the first 8 bytes of parameters in registers (%ecx and %edx). | |
597 // We're only interested in the stack space used for parameters, so | |
598 // so subtract 8 and don't let the size go below 0. | |
599 if (*name[0] == '@') { | |
600 if (*stack_param_size > 8) { | |
601 *stack_param_size -= 8; | |
602 } else { | |
603 *stack_param_size = 0; | |
604 } | |
605 } | |
606 | |
607 // Undecorate the name by moving it one character to the left in its | |
608 // buffer, and terminating it where the last '@' had been. | |
609 WindowsStringUtils::safe_wcsncpy(*name, length, | |
610 *name + 1, last_at - *name - 1); | |
611 } else if (*name[0] == '_') { | |
612 // This symbol's name is encoded according to the cdecl rules. The | |
613 // name doesn't end in a '@' character followed by a decimal positive | |
614 // integer, so it's not a stdcall name. Strip off the leading | |
615 // underscore. | |
616 WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length); | |
617 } | |
618 } | |
619 } | |
620 | |
621 return true; | |
622 } | |
623 | |
624 // static | |
625 int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) { | |
626 // This implementation is highly x86-specific. | |
627 | |
628 // Gather the symbols corresponding to data. | |
629 CComPtr<IDiaEnumSymbols> data_children; | |
630 if (FAILED(function->findChildren(SymTagData, NULL, nsNone, | |
631 &data_children))) { | |
632 return 0; | |
633 } | |
634 | |
635 // lowest_base is the lowest %ebp-relative byte offset used for a parameter. | |
636 // highest_end is one greater than the highest offset (i.e. base + length). | |
637 // Stack parameters are assumed to be contiguous, because in reality, they | |
638 // are. | |
639 int lowest_base = INT_MAX; | |
640 int highest_end = INT_MIN; | |
641 | |
642 CComPtr<IDiaSymbol> child; | |
643 DWORD count; | |
644 while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) { | |
645 // If any operation fails at this point, just proceed to the next child. | |
646 // Use the next_child label instead of continue because child needs to | |
647 // be released before it's reused. Declare constructable/destructable | |
648 // types early to avoid gotos that cross initializations. | |
649 CComPtr<IDiaSymbol> child_type; | |
650 | |
651 // DataIsObjectPtr is only used for |this|. Because |this| can be passed | |
652 // as a stack parameter, look for it in addition to traditional | |
653 // parameters. | |
654 DWORD child_kind; | |
655 if (FAILED(child->get_dataKind(&child_kind)) || | |
656 (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) { | |
657 goto next_child; | |
658 } | |
659 | |
660 // Only concentrate on register-relative parameters. Parameters may also | |
661 // be enregistered (passed directly in a register), but those don't | |
662 // consume any stack space, so they're not of interest. | |
663 DWORD child_location_type; | |
664 if (FAILED(child->get_locationType(&child_location_type)) || | |
665 child_location_type != LocIsRegRel) { | |
666 goto next_child; | |
667 } | |
668 | |
669 // Of register-relative parameters, the only ones that make any sense are | |
670 // %ebp- or %esp-relative. Note that MSVC's debugging information always | |
671 // gives parameters as %ebp-relative even when a function doesn't use a | |
672 // traditional frame pointer and stack parameters are accessed relative to | |
673 // %esp, so just look for %ebp-relative parameters. If you wanted to | |
674 // access parameters, you'd probably want to treat these %ebp-relative | |
675 // offsets as if they were relative to %esp before a function's prolog | |
676 // executed. | |
677 DWORD child_register; | |
678 if (FAILED(child->get_registerId(&child_register)) || | |
679 child_register != CV_REG_EBP) { | |
680 goto next_child; | |
681 } | |
682 | |
683 LONG child_register_offset; | |
684 if (FAILED(child->get_offset(&child_register_offset))) { | |
685 goto next_child; | |
686 } | |
687 | |
688 // IDiaSymbol::get_type can succeed but still pass back a NULL value. | |
689 if (FAILED(child->get_type(&child_type)) || !child_type) { | |
690 goto next_child; | |
691 } | |
692 | |
693 ULONGLONG child_length; | |
694 if (FAILED(child_type->get_length(&child_length))) { | |
695 goto next_child; | |
696 } | |
697 | |
698 int child_end = child_register_offset + static_cast<ULONG>(child_length); | |
699 if (child_register_offset < lowest_base) { | |
700 lowest_base = child_register_offset; | |
701 } | |
702 if (child_end > highest_end) { | |
703 highest_end = child_end; | |
704 } | |
705 | |
706 next_child: | |
707 child.Release(); | |
708 } | |
709 | |
710 int param_size = 0; | |
711 // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest | |
712 // possible address to find a stack parameter before executing a function's | |
713 // prolog (see above). Some optimizations cause parameter offsets to be | |
714 // lower than 4, but we're not concerned with those because we're only | |
715 // looking for parameters contained in addresses higher than where the | |
716 // return address is stored. | |
717 if (lowest_base < 4) { | |
718 lowest_base = 4; | |
719 } | |
720 if (highest_end > lowest_base) { | |
721 // All stack parameters are pushed as at least 4-byte quantities. If the | |
722 // last type was narrower than 4 bytes, promote it. This assumes that all | |
723 // parameters' offsets are 4-byte-aligned, which is always the case. Only | |
724 // worry about the last type, because we're not summing the type sizes, | |
725 // just looking at the lowest and highest offsets. | |
726 int remainder = highest_end % 4; | |
727 if (remainder) { | |
728 highest_end += 4 - remainder; | |
729 } | |
730 | |
731 param_size = highest_end - lowest_base; | |
732 } | |
733 | |
734 return param_size; | |
735 } | |
736 | |
737 bool PDBSourceLineWriter::WriteMap(FILE *map_file) { | |
738 output_ = map_file; | |
739 | |
740 bool ret = PrintPDBInfo() && | |
741 PrintSourceFiles() && | |
742 PrintFunctions() && | |
743 PrintFrameData(); | |
744 | |
745 output_ = NULL; | |
746 return ret; | |
747 } | |
748 | |
749 void PDBSourceLineWriter::Close() { | |
750 session_.Release(); | |
751 } | |
752 | |
753 bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) { | |
754 if (!info) { | |
755 return false; | |
756 } | |
757 | |
758 info->debug_file.clear(); | |
759 info->debug_identifier.clear(); | |
760 info->cpu.clear(); | |
761 | |
762 CComPtr<IDiaSymbol> global; | |
763 if (FAILED(session_->get_globalScope(&global))) { | |
764 return false; | |
765 } | |
766 | |
767 // All CPUs in CV_CPU_TYPE_e (cvconst.h) below 0x10 are x86. There's no | |
768 // single specific constant to use. | |
769 DWORD platform; | |
770 if (SUCCEEDED(global->get_platform(&platform)) && platform < 0x10) { | |
771 info->cpu = L"x86"; | |
772 } else { | |
773 // Unexpected, but handle gracefully. | |
774 info->cpu = L"unknown"; | |
775 } | |
776 | |
777 // DWORD* and int* are not compatible. This is clean and avoids a cast. | |
778 DWORD age; | |
779 if (FAILED(global->get_age(&age))) { | |
780 return false; | |
781 } | |
782 | |
783 bool uses_guid; | |
784 if (!UsesGUID(&uses_guid)) { | |
785 return false; | |
786 } | |
787 | |
788 if (uses_guid) { | |
789 GUID guid; | |
790 if (FAILED(global->get_guid(&guid))) { | |
791 return false; | |
792 } | |
793 | |
794 // Use the same format that the MS symbol server uses in filesystem | |
795 // hierarchies. | |
796 wchar_t age_string[9]; | |
797 swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]), | |
798 L"%x", age); | |
799 | |
800 // remove when VC++7.1 is no longer supported | |
801 age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0'; | |
802 | |
803 info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid); | |
804 info->debug_identifier.append(age_string); | |
805 } else { | |
806 DWORD signature; | |
807 if (FAILED(global->get_signature(&signature))) { | |
808 return false; | |
809 } | |
810 | |
811 // Use the same format that the MS symbol server uses in filesystem | |
812 // hierarchies. | |
813 wchar_t identifier_string[17]; | |
814 swprintf(identifier_string, | |
815 sizeof(identifier_string) / sizeof(identifier_string[0]), | |
816 L"%08X%x", signature, age); | |
817 | |
818 // remove when VC++7.1 is no longer supported | |
819 identifier_string[sizeof(identifier_string) / | |
820 sizeof(identifier_string[0]) - 1] = L'\0'; | |
821 | |
822 info->debug_identifier = identifier_string; | |
823 } | |
824 | |
825 CComBSTR debug_file_string; | |
826 if (FAILED(global->get_symbolsFileName(&debug_file_string))) { | |
827 return false; | |
828 } | |
829 info->debug_file = | |
830 WindowsStringUtils::GetBaseName(wstring(debug_file_string)); | |
831 | |
832 return true; | |
833 } | |
834 | |
835 bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) { | |
836 if (!uses_guid) | |
837 return false; | |
838 | |
839 CComPtr<IDiaSymbol> global; | |
840 if (FAILED(session_->get_globalScope(&global))) | |
841 return false; | |
842 | |
843 GUID guid; | |
844 if (FAILED(global->get_guid(&guid))) | |
845 return false; | |
846 | |
847 DWORD signature; | |
848 if (FAILED(global->get_signature(&signature))) | |
849 return false; | |
850 | |
851 // There are two possibilities for guid: either it's a real 128-bit GUID | |
852 // as identified in a code module by a new-style CodeView record, or it's | |
853 // a 32-bit signature (timestamp) as identified by an old-style record. | |
854 // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h. | |
855 // | |
856 // Because DIA doesn't provide a way to directly determine whether a module | |
857 // uses a GUID or a 32-bit signature, this code checks whether the first 32 | |
858 // bits of guid are the same as the signature, and if the rest of guid is | |
859 // zero. If so, then with a pretty high degree of certainty, there's an | |
860 // old-style CodeView record in use. This method will only falsely find an | |
861 // an old-style CodeView record if a real 128-bit GUID has its first 32 | |
862 // bits set the same as the module's signature (timestamp) and the rest of | |
863 // the GUID is set to 0. This is highly unlikely. | |
864 | |
865 GUID signature_guid = {signature}; // 0-initializes other members | |
866 *uses_guid = !IsEqualGUID(guid, signature_guid); | |
867 return true; | |
868 } | |
869 | |
870 } // namespace google_breakpad | |
OLD | NEW |