diff options
author | Nelson Billing <nbilling@google.com> | 2019-06-24 11:52:48 -0700 |
---|---|---|
committer | Nelson Billing <nbilling@google.com> | 2019-06-24 18:55:02 +0000 |
commit | 6ca3f8bbe56951db922fa3b567d7ec441093f96e (patch) | |
tree | 23ba14440e1ef1dfb5022977d171f7c9391110b2 /src/tools/windows/converter | |
parent | Fix 'debug_file' in PESourceLineWriter. (diff) | |
download | breakpad-6ca3f8bbe56951db922fa3b567d7ec441093f96e.tar.xz |
Add PE-only MD support to Windows symbol converter.
- Only 64-bit PEs supported.
- Re-add some scripts that were missed in initial move of code.
- Change msdia120.dll dependency to msdia140.dll.
- Add tests for Intel, AMD, and NVidia Microsoft Symbol Stores.
- Windows symbol converter now attempts to fall back to PE-only metadata
when it fails to locate a PDB.
- Remove the 'binary' folder under converter_exe. Need to think more
about how a deployment should look and what tool(s) to use in creating
one.
Change-Id: I52e42cbe5e759874a25114c2483e8b50d73fdf77
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1670098
Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
Diffstat (limited to 'src/tools/windows/converter')
-rw-r--r-- | src/tools/windows/converter/ms_symbol_server_converter.cc | 137 | ||||
-rw-r--r-- | src/tools/windows/converter/ms_symbol_server_converter.h | 16 |
2 files changed, 145 insertions, 8 deletions
diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc index 6cc67700..e3215ba5 100644 --- a/src/tools/windows/converter/ms_symbol_server_converter.cc +++ b/src/tools/windows/converter/ms_symbol_server_converter.cc @@ -42,6 +42,7 @@ #include "tools/windows/converter/ms_symbol_server_converter.h" #include "common/windows/pdb_source_line_writer.h" +#include "common/windows/pe_source_line_writer.h" #include "common/windows/string_utils-inl.h" // SYMOPT_NO_PROMPTS is not defined in earlier platform SDKs. Define it @@ -445,7 +446,10 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile( string pdb_file; LocateResult result = LocateSymbolFile(missing, &pdb_file); if (result != LOCATE_SUCCESS) { - return result; + fprintf(stderr, "Fallback to PE-only symbol generation for: %s\n", + missing.debug_file.c_str()); + return LocateAndConvertPEFile(missing, keep_pe_file, converted_symbol_file, + out_pe_file); } if (symbol_file && keep_symbol_file) { @@ -525,7 +529,7 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile( #if _MSC_VER >= 1400 // MSVC 2005/8 errno_t err; if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) - != 0) { + != 0) { #else // _MSC_VER >= 1400 // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier // environments. Don't use fopen with MSVC8 and later, because it's @@ -536,12 +540,12 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile( err = -1; #endif // _MSC_VER >= 1400 fprintf(stderr, "LocateAndConvertSymbolFile: " - "fopen_s: error %d for %s %s %s %s\n", - err, - missing.debug_file.c_str(), - missing.debug_identifier.c_str(), - missing.version.c_str(), - converted_symbol_file->c_str()); + "fopen_s: error %d for %s %s %s %s\n", + err, + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + converted_symbol_file->c_str()); return LOCATE_FAILURE; } @@ -573,4 +577,121 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile( return LOCATE_SUCCESS; } +MSSymbolServerConverter::LocateResult +MSSymbolServerConverter::LocateAndConvertPEFile( + const MissingSymbolInfo &missing, + bool keep_pe_file, + string *converted_symbol_file, + string *out_pe_file) { + assert(converted_symbol_file); + converted_symbol_file->clear(); + + string pe_file; + MSSymbolServerConverter::LocateResult result = LocatePEFile(missing, + &pe_file); + if (result != LOCATE_SUCCESS) { + fprintf(stderr, "WARNING: Could not download: %s\n", pe_file.c_str()); + return result; + } + + if (out_pe_file && keep_pe_file) { + *out_pe_file = pe_file; + } + + // Conversion may fail because the file is corrupt. If a broken file is + // kept in the local cache, LocatePEFile will not hit the network again + // to attempt to locate it. To guard against problems like this, the + // PE file in the local cache will be removed if conversion fails. + AutoDeleter pe_deleter(pe_file); + + // Be sure that it's a .exe or .dll file, since we'll be replacing extension + // with .sym for the converted file's name. + string pe_extension = pe_file.substr(pe_file.length() - 4); + // strcasecmp is called _stricmp here. + if (_stricmp(pe_extension.c_str(), ".exe") != 0 && + _stricmp(pe_extension.c_str(), ".dll") != 0) { + fprintf(stderr, "LocateAndConvertPEFile: " + "no .dll/.exe extension for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pe_file.c_str()); + return LOCATE_FAILURE; + } + + *converted_symbol_file = pe_file.substr(0, pe_file.length() - 4) + ".sym"; + + FILE *converted_output = NULL; +#if _MSC_VER >= 1400 // MSVC 2005/8 + errno_t err; + if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) + != 0) { +#else // _MSC_VER >= 1400 + // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier + // environments. Don't use fopen with MSVC8 and later, because it's + // deprecated. fopen does not provide reliable error codes, so just use + // -1 in the event of a failure. + int err; + if (!(converted_output = fopen(converted_symbol_file->c_str(), "w"))) { + err = -1; +#endif // _MSC_VER >= 1400 + fprintf(stderr, "LocateAndConvertPEFile: " + "fopen_s: error %d for %s %s %s %s\n", + err, + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + converted_symbol_file->c_str()); + return LOCATE_FAILURE; + } + AutoDeleter sym_deleter(*converted_symbol_file); + + wstring pe_file_w; + if (!WindowsStringUtils::safe_mbstowcs(pe_file, &pe_file_w)) { + fprintf(stderr, + "LocateAndConvertPEFile: " + "WindowsStringUtils::safe_mbstowcs failed for %s\n", + pe_file.c_str()); + return LOCATE_FAILURE; + } + PESourceLineWriter writer(pe_file_w); + PDBModuleInfo module_info; + if (!writer.GetModuleInfo(&module_info)) { + fprintf(stderr, "LocateAndConvertPEFile: " + "PESourceLineWriter::GetModuleInfo failed for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pe_file.c_str()); + return LOCATE_FAILURE; + } + if (module_info.cpu.compare(L"x86_64") != 0) { + // This module is not x64 so we cannot generate Breakpad symbols from the + // PE alone. Don't delete PE-- no need to retry download. + pe_deleter.Release(); + return LOCATE_FAILURE; + } + + bool success = writer.WriteSymbols(converted_output); + fclose(converted_output); + + if (!success) { + fprintf(stderr, "LocateAndConvertPEFile: " + "PESourceLineWriter::WriteMap failed for %s %s %s %s\n", + missing.debug_file.c_str(), + missing.debug_identifier.c_str(), + missing.version.c_str(), + pe_file.c_str()); + return LOCATE_FAILURE; + } + + if (keep_pe_file) { + pe_deleter.Release(); + } + + sym_deleter.Release(); + + return LOCATE_SUCCESS; +} + } // namespace google_breakpad diff --git a/src/tools/windows/converter/ms_symbol_server_converter.h b/src/tools/windows/converter/ms_symbol_server_converter.h index d601b433..401f7c34 100644 --- a/src/tools/windows/converter/ms_symbol_server_converter.h +++ b/src/tools/windows/converter/ms_symbol_server_converter.h @@ -177,6 +177,22 @@ class MSSymbolServerConverter { string *symbol_file, string *pe_file); + // Calls LocatePEFile and converts the returned PE file to the + // dumped-symbol format, storing it adjacent to the PE file. The + // only conversion supported is from PE files. Returns the return + // value of LocatePEFile, or if LocatePEFile succeeds but + // conversion fails, returns LOCATE_FAILURE. The pathname to the + // PE file and to the converted symbol file are returned in + // |converted_symbol_file| and |pe_file|. |pe_file| is optional and may be + // NULL. If only the converted symbol file is desired, set |keep_pe_file| + // to false to indicate that the executable file (exe, dll) should be deleted + // after conversion. + // NOTE: Currrently only supports x64 PEs. + LocateResult LocateAndConvertPEFile(const MissingSymbolInfo &missing, + bool keep_pe_file, + string *converted_symbol_file, + string *pe_file); + private: // Locates the PDB or PE file (DLL or EXE) specified by the identifying // information in |debug_or_code_file| and |debug_or_code_id|, by checking |