/thirdparty/breakpad/common/windows/pdb_source_line_writer.cc

http://github.com/tomahawk-player/tomahawk · C++ · 1001 lines · 676 code · 132 blank · 193 comment · 189 complexity · 901460afb69fb1c997d30ed44f246f59 MD5 · raw file

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