summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/tools/windows
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /toolkit/crashreporter/google-breakpad/src/tools/windows
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/tools/windows')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exebin0 -> 141824 bytes
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exebin0 -> 243712 bytes
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc752
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp46
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h235
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj368
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd33
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc807
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp57
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc757
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h99
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h96
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc326
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h62
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt5
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes2
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc61
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h51
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc307
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc278
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd86
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc73
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj242
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc244
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat23
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc394
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp50
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp46
33 files changed, 5769 insertions, 0 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe
new file mode 100644
index 0000000000..3a2dfd8e50
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe
Binary files differ
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe
new file mode 100644
index 0000000000..09d2a55b5c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe
Binary files differ
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
new file mode 100644
index 0000000000..2b40faeeb5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
@@ -0,0 +1,752 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ms_symbol_server_converter.cc: Obtain symbol files from a Microsoft
+// symbol server, and convert them to Breakpad's dumped format.
+//
+// See ms_symbol_server_converter.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <pathcch.h>
+
+#include <cassert>
+#include <cstdio>
+
+#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
+// in that case, in the event that this code is used with a newer version
+// of DbgHelp at runtime that recognizes the option. The presence of this
+// bit in the symbol options should not harm earlier versions of DbgHelp.
+#ifndef SYMOPT_NO_PROMPTS
+#define SYMOPT_NO_PROMPTS 0x00080000
+#endif // SYMOPT_NO_PROMPTS
+
+namespace {
+
+std::wstring GetExeDirectory() {
+ wchar_t directory[MAX_PATH];
+
+ // Get path to this process exe.
+ DWORD result = GetModuleFileName(/*hModule=*/nullptr, directory, MAX_PATH);
+ if (result <= 0 || result == MAX_PATH) {
+ fprintf(stderr,
+ "GetExeDirectory: failed to get path to process exe.\n");
+ return L"";
+ }
+ HRESULT hr = PathCchRemoveFileSpec(directory, result + 1);
+ if (hr != S_OK) {
+ fprintf(stderr,
+ "GetExeDirectory: failed to remove basename from path '%ls'.\n",
+ directory);
+ return L"";
+ }
+
+ return std::wstring(directory);
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+// Use sscanf_s if it is available, to quench the warning about scanf being
+// deprecated. Use scanf where sscanf_is not available. Note that the
+// parameters passed to sscanf and sscanf_s are only compatible as long as
+// fields of type c, C, s, S, and [ are not used.
+#if _MSC_VER >= 1400 // MSVC 2005/8
+#define SSCANF sscanf_s
+#else // _MSC_VER >= 1400
+#define SSCANF sscanf
+#endif // _MSC_VER >= 1400
+
+bool GUIDOrSignatureIdentifier::InitializeFromString(
+ const string &identifier) {
+ type_ = TYPE_NONE;
+
+ size_t length = identifier.length();
+
+ if (length > 32 && length <= 40) {
+ // GUID
+ if (SSCANF(identifier.c_str(),
+ "%08X%04hX%04hX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%X",
+ &guid_.Data1, &guid_.Data2, &guid_.Data3,
+ &guid_.Data4[0], &guid_.Data4[1],
+ &guid_.Data4[2], &guid_.Data4[3],
+ &guid_.Data4[4], &guid_.Data4[5],
+ &guid_.Data4[6], &guid_.Data4[7],
+ &age_) != 12) {
+ return false;
+ }
+
+ type_ = TYPE_GUID;
+ } else if (length > 8 && length <= 15) {
+ // Signature
+ if (SSCANF(identifier.c_str(), "%08X%x", &signature_, &age_) != 2) {
+ return false;
+ }
+
+ type_ = TYPE_SIGNATURE;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+#undef SSCANF
+
+MSSymbolServerConverter::MSSymbolServerConverter(
+ const string &local_cache, const vector<string> &symbol_servers)
+ : symbol_path_(),
+ fail_dns_(false),
+ fail_timeout_(false),
+ fail_not_found_(false) {
+ // Setting local_cache can be done without verifying that it exists because
+ // SymSrv will create it if it is missing - any creation failures will occur
+ // at that time, so there's nothing to check here, making it safe to
+ // assign this in the constructor.
+
+ assert(symbol_servers.size() > 0);
+
+#if !defined(NDEBUG)
+ // These are characters that are interpreted as having special meanings in
+ // symbol_path_.
+ const char kInvalidCharacters[] = "*;";
+ assert(local_cache.find_first_of(kInvalidCharacters) == string::npos);
+#endif // !defined(NDEBUG)
+
+ for (vector<string>::const_iterator symbol_server = symbol_servers.begin();
+ symbol_server != symbol_servers.end();
+ ++symbol_server) {
+ // The symbol path format is explained by
+ // http://msdn.microsoft.com/library/en-us/debug/base/using_symsrv.asp .
+ // "srv*" is the same as "symsrv*symsrv.dll*", which means that
+ // symsrv.dll is to be responsible for locating symbols. symsrv.dll
+ // interprets the rest of the string as a series of symbol stores separated
+ // by '*'. "srv*local_cache*symbol_server" means to check local_cache
+ // first for the symbol file, and if it is not found there, to check
+ // symbol_server. Symbol files found on the symbol server will be placed
+ // in the local cache, decompressed.
+ //
+ // Multiple specifications in this format may be presented, separated by
+ // semicolons.
+
+ assert((*symbol_server).find_first_of(kInvalidCharacters) == string::npos);
+ symbol_path_ += "srv*" + local_cache + "*" + *symbol_server + ";";
+ }
+
+ // Strip the trailing semicolon.
+ symbol_path_.erase(symbol_path_.length() - 1);
+}
+
+// A stack-based class that manages SymInitialize and SymCleanup calls.
+class AutoSymSrv {
+ public:
+ AutoSymSrv() : initialized_(false) {}
+
+ ~AutoSymSrv() {
+ if (!Cleanup()) {
+ // Print the error message here, because destructors have no return
+ // value.
+ fprintf(stderr, "~AutoSymSrv: SymCleanup: error %lu\n", GetLastError());
+ }
+ }
+
+ bool Initialize(HANDLE process, char *path, bool invade_process) {
+ process_ = process;
+
+ // TODO(nbilling): Figure out why dbghelp.dll is being loaded from
+ // system32/SysWOW64 before exe folder.
+
+ // Attempt to locate and load dbghelp.dll beside the process exe. This is
+ // somewhat of a workaround to loader delay load behavior that is occurring
+ // when we call into symsrv APIs. dbghelp.dll must be loaded from beside
+ // the process exe so that we are guaranteed to find symsrv.dll alongside
+ // dbghelp.dll (a security requirement of dbghelp.dll) and so that the
+ // symsrv.dll file that is loaded has a symsrv.yes file alongside it (a
+ // requirement of symsrv.dll when accessing Microsoft-owned symbol
+ // servers).
+ // 'static local' because we don't care about the value but we need the
+ // initialization to happen exactly once.
+ static HMODULE dbghelp_module = [] () -> HMODULE {
+ std::wstring exe_directory = GetExeDirectory();
+ if (exe_directory.empty()) {
+ return nullptr;
+ }
+ std::wstring dbghelp_path = exe_directory + L"\\dbghelp.dll";
+ return LoadLibrary(dbghelp_path.c_str());
+ }();
+ if (dbghelp_module == nullptr) {
+ fprintf(stderr,
+ "AutoSymSrv::Initialize: failed to load dbghelp.dll beside exe.");
+ return false;
+ }
+
+ initialized_ = SymInitialize(process, path, invade_process) == TRUE;
+ return initialized_;
+ }
+
+ bool Cleanup() {
+ if (initialized_) {
+ if (SymCleanup(process_)) {
+ initialized_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ HANDLE process_;
+ bool initialized_;
+};
+
+// A stack-based class that "owns" a pathname and deletes it when destroyed,
+// unless told not to by having its Release() method called. Early deletions
+// are supported by calling Delete().
+class AutoDeleter {
+ public:
+ explicit AutoDeleter(const string &path) : path_(path) {}
+
+ ~AutoDeleter() {
+ int error;
+ if ((error = Delete()) != 0) {
+ // Print the error message here, because destructors have no return
+ // value.
+ fprintf(stderr, "~AutoDeleter: Delete: error %d for %s\n",
+ error, path_.c_str());
+ }
+ }
+
+ int Delete() {
+ if (path_.empty())
+ return 0;
+
+ int error = remove(path_.c_str());
+ Release();
+ return error;
+ }
+
+ void Release() {
+ path_.clear();
+ }
+
+ private:
+ string path_;
+};
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
+ const string &debug_or_code_id,
+ const string &version,
+ string *file_name) {
+ assert(file_name);
+ file_name->clear();
+
+ GUIDOrSignatureIdentifier identifier;
+ if (!identifier.InitializeFromString(debug_or_code_id)) {
+ fprintf(stderr,
+ "LocateFile: Unparseable identifier for %s %s %s\n",
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ HANDLE process = GetCurrentProcess(); // CloseHandle is not needed.
+ AutoSymSrv symsrv;
+ if (!symsrv.Initialize(process,
+ const_cast<char *>(symbol_path_.c_str()),
+ false)) {
+ fprintf(stderr, "LocateFile: SymInitialize: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ if (!SymRegisterCallback64(process, SymCallback,
+ reinterpret_cast<ULONG64>(this))) {
+ fprintf(stderr,
+ "LocateFile: SymRegisterCallback64: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ // SYMOPT_DEBUG arranges for SymCallback to be called with additional
+ // debugging information. This is used to determine the nature of failures.
+ DWORD options = SymGetOptions() | SYMOPT_DEBUG | SYMOPT_NO_PROMPTS |
+ SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_SECURE;
+ SymSetOptions(options);
+
+ // SymCallback will set these as needed inisde the SymFindFileInPath call.
+ fail_dns_ = false;
+ fail_timeout_ = false;
+ fail_not_found_ = false;
+
+ // Do the lookup.
+ char path[MAX_PATH];
+ if (!SymFindFileInPath(
+ process, NULL,
+ const_cast<char *>(debug_or_code_file.c_str()),
+ const_cast<void *>(identifier.guid_or_signature_pointer()),
+ identifier.age(), 0,
+ identifier.type() == GUIDOrSignatureIdentifier::TYPE_GUID ?
+ SSRVOPT_GUIDPTR : SSRVOPT_DWORDPTR,
+ path, SymFindFileInPathCallback, this)) {
+ DWORD error = GetLastError();
+ if (error == ERROR_FILE_NOT_FOUND) {
+ // This can be returned for a number of reasons. Use the crumbs
+ // collected by SymCallback to determine which one is relevant.
+
+ // These errors are possibly transient.
+ if (fail_dns_ || fail_timeout_) {
+ return LOCATE_RETRY;
+ }
+
+ // This is an authoritiative file-not-found message.
+ if (fail_not_found_) {
+ fprintf(stderr,
+ "LocateFile: SymFindFileInPath: LOCATE_NOT_FOUND error "
+ "for %s %s %s\n",
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_NOT_FOUND;
+ }
+
+ // If the error is FILE_NOT_FOUND but none of the known error
+ // conditions are matched, fall through to LOCATE_FAILURE.
+ }
+
+ fprintf(stderr,
+ "LocateFile: SymFindFileInPath: error %lu for %s %s %s\n",
+ error,
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ // Making sure path is null-terminated.
+ path[MAX_PATH - 1] = '\0';
+
+ // The AutoDeleter ensures that the file is only kept when returning
+ // LOCATE_SUCCESS.
+ AutoDeleter deleter(path);
+
+ // Do the cleanup here even though it will happen when symsrv goes out of
+ // scope, to allow it to influence the return value.
+ if (!symsrv.Cleanup()) {
+ fprintf(stderr, "LocateFile: SymCleanup: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ deleter.Release();
+
+ printf("Downloaded: %s\n", path);
+ *file_name = path;
+ return LOCATE_SUCCESS;
+}
+
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocatePEFile(const MissingSymbolInfo &missing,
+ string *pe_file) {
+ return LocateFile(missing.code_file, missing.code_identifier,
+ missing.version, pe_file);
+}
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo &missing,
+ string *symbol_file) {
+ return LocateFile(missing.debug_file, missing.debug_identifier,
+ missing.version, symbol_file);
+}
+
+
+// static
+BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process,
+ ULONG action,
+ ULONG64 data,
+ ULONG64 context) {
+ MSSymbolServerConverter *self =
+ reinterpret_cast<MSSymbolServerConverter *>(context);
+
+ switch (action) {
+ case CBA_EVENT: {
+ IMAGEHLP_CBA_EVENT *cba_event =
+ reinterpret_cast<IMAGEHLP_CBA_EVENT *>(data);
+
+ // Put the string into a string object to be able to use string::find
+ // for substring matching. This is important because the not-found
+ // message does not use the entire string but is appended to the URL
+ // that SymSrv attempted to retrieve.
+ string desc(cba_event->desc);
+
+ // desc_action maps strings (in desc) to boolean pointers that are to
+ // be set to true if the string matches.
+ struct desc_action {
+ const char *desc; // The substring to match.
+ bool *action; // On match, this pointer will be set to true.
+ };
+
+ static const desc_action desc_actions[] = {
+ // When a DNS error occurs, it could be indiciative of network
+ // problems.
+ { "SYMSRV: The server name or address could not be resolved\n",
+ &self->fail_dns_ },
+
+ // This message is produced if no connection is opened.
+ { "SYMSRV: A connection with the server could not be established\n",
+ &self->fail_timeout_ },
+
+ // This message is produced if a connection is established but the
+ // server fails to respond to the HTTP request.
+ { "SYMSRV: The operation timed out\n",
+ &self->fail_timeout_ },
+
+ // This message is produced when the requested file is not found,
+ // even if one or more of the above messages are also produced.
+ // It's trapped to distinguish between not-found and unknown-failure
+ // conditions. Note that this message will not be produced if a
+ // connection is established and the server begins to respond to the
+ // HTTP request but does not finish transmitting the file.
+ { " not found\n",
+ &self->fail_not_found_ }
+ };
+
+ for (int desc_action_index = 0;
+ desc_action_index <
+ static_cast<int>(sizeof(desc_actions) / sizeof(desc_action));
+ ++desc_action_index) {
+ if (desc.find(desc_actions[desc_action_index].desc) != string::npos) {
+ *(desc_actions[desc_action_index].action) = true;
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ // This function is a mere fly on the wall. Treat everything as unhandled.
+ return FALSE;
+}
+
+// static
+BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback(
+ const char *filename, void *context) {
+ // FALSE ends the search, indicating that the located symbol file is
+ // satisfactory.
+ return FALSE;
+}
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateAndConvertSymbolFile(
+ const MissingSymbolInfo &missing,
+ bool keep_symbol_file,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ string *symbol_file,
+ string *out_pe_file) {
+ assert(converted_symbol_file);
+ converted_symbol_file->clear();
+ if (symbol_file) {
+ symbol_file->clear();
+ }
+
+ string pdb_file;
+ LocateResult result = LocateSymbolFile(missing, &pdb_file);
+ if (result != LOCATE_SUCCESS) {
+ 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) {
+ *symbol_file = pdb_file;
+ }
+
+ // The conversion of a symbol file for a Windows 64-bit module requires
+ // loading of the executable file. If there is no executable file, convert
+ // using only the PDB file. Without an executable file, the conversion will
+ // fail for 64-bit modules but it should succeed for 32-bit modules.
+ string pe_file;
+ result = LocatePEFile(missing, &pe_file);
+ if (result != LOCATE_SUCCESS) {
+ fprintf(stderr, "WARNING: Could not download: %s\n", pe_file.c_str());
+ }
+
+ 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, LocateSymbolFile will not hit the network again
+ // to attempt to locate it. To guard against problems like this, the
+ // symbol file in the local cache will be removed if conversion fails.
+ AutoDeleter pdb_deleter(pdb_file);
+ AutoDeleter pe_deleter(pe_file);
+
+ // Be sure that it's a .pdb file, since we'll be replacing .pdb with .sym
+ // for the converted file's name.
+ string pdb_extension = pdb_file.substr(pdb_file.length() - 4);
+ // strcasecmp is called _stricmp here.
+ if (_stricmp(pdb_extension.c_str(), ".pdb") != 0) {
+ fprintf(stderr, "LocateAndConvertSymbolFile: "
+ "no .pdb extension for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pdb_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ PDBSourceLineWriter writer;
+ wstring pe_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(pe_file, &pe_file_w)) {
+ fprintf(stderr,
+ "LocateAndConvertSymbolFile: "
+ "WindowsStringUtils::safe_mbstowcs failed for %s\n",
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+ wstring pdb_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(pdb_file, &pdb_file_w)) {
+ fprintf(stderr,
+ "LocateAndConvertSymbolFile: "
+ "WindowsStringUtils::safe_mbstowcs failed for %ws\n",
+ pdb_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+ if (!writer.Open(pdb_file_w, PDBSourceLineWriter::PDB_FILE)) {
+ fprintf(stderr,
+ "ERROR: PDBSourceLineWriter::Open failed for %s %s %s %ws\n",
+ missing.debug_file.c_str(), missing.debug_identifier.c_str(),
+ missing.version.c_str(), pdb_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+ if (!writer.SetCodeFile(pe_file_w)) {
+ fprintf(stderr,
+ "ERROR: PDBSourceLineWriter::SetCodeFile failed for %s %s %s %ws\n",
+ missing.debug_file.c_str(), missing.debug_identifier.c_str(),
+ missing.version.c_str(), pe_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ *converted_symbol_file = pdb_file.substr(0, pdb_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, "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());
+ return LOCATE_FAILURE;
+ }
+
+ AutoDeleter sym_deleter(*converted_symbol_file);
+
+ bool success = writer.WriteSymbols(converted_output);
+ fclose(converted_output);
+
+ if (!success) {
+ fprintf(stderr, "LocateAndConvertSymbolFile: "
+ "PDBSourceLineWriter::WriteMap failed for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pdb_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ if (keep_symbol_file) {
+ pdb_deleter.Release();
+ }
+
+ if (keep_pe_file) {
+ pe_deleter.Release();
+ }
+
+ sym_deleter.Release();
+
+ 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/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp
new file mode 100644
index 0000000000..57ec790686
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp
@@ -0,0 +1,46 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ms_symbol_server_converter',
+ 'type': 'static_library',
+ 'msvs_guid': '1463C4CD-23FC-4DE9-BFDE-283338200157',
+ 'sources': [
+ 'ms_symbol_server_converter.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h
new file mode 100644
index 0000000000..401f7c3443
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h
@@ -0,0 +1,235 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ms_symbol_server_converter.h: Obtain symbol files from a Microsoft
+// symbol server, and convert them to Breakpad's dumped format.
+//
+// At runtime, MSSymbolServerConverter and code that it calls depend on being
+// able to locate suitable versions of dbghelp.dll and symsrv.dll. For best
+// results, place these files in the same directory as the executable.
+// dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are
+// both redistributable, as indicated by the package's redist.txt file.
+//
+// When connecting to Microsoft's symbol server at
+// http://msdl.microsoft.com/download/symbols/, which provides access to
+// symbols for the operating system itself, symsrv.dll requires agreement to
+// Microsoft's "Terms of Use for Microsoft Symbols and Binaries." Because this
+// library places the symbol engine into a promptless mode, the dialog with the
+// terms will not appear, and use of Microsoft's symbol server will not be
+// possible. To indicate agreement to the terms, create a file called
+// symsrv.yes in the same directory as symsrv.dll. (Note that symsrv.dll will
+// also recognize a symsrv.no file as indicating that you do not accept the
+// terms; the .yes file takes priority over the .no file.) The terms of use
+// are contained within symsrv.dll; they were formerly available online at
+// http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but
+// do not appear to be available online any longer as of January, 2007. It is
+// possible to view the terms from within WinDbg (Debugging Tools for Windows)
+// by removing any symsrv.yes and symsrv.no files from WinDbg's directory,
+// setting the symbol path to include Microsoft's symbol server (.sympath), and
+// attempting to load symbols from their server (.reload).
+//
+// This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8,
+// included with Microsoft Visual Studio 8 in Common7/IDE. This has also been
+// tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633,
+// included with the same versions of Debugging Tools for Windows, available at
+// http://www.microsoft.com/whdc/devtools/debugging/ .
+//
+// Author: Mark Mentovai
+
+#ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
+#define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
+
+#include <windows.h>
+
+#include <string>
+#include <vector>
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+// MissingSymbolInfo contains the subset of the information in the processor's
+// CodeModule structure relevant to obtaining a missing symbol file. Only
+// debug_file and debug_identifier are relevant in actually obtaining the
+// missing file; the other fields are for convenience.
+struct MissingSymbolInfo {
+ string code_file;
+ string code_identifier;
+ string debug_file;
+ string debug_identifier;
+ string version;
+};
+
+class GUIDOrSignatureIdentifier {
+ public:
+ enum GUIDOrSignatureType {
+ TYPE_NONE = 0,
+ TYPE_GUID,
+ TYPE_SIGNATURE
+ };
+
+ GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {}
+
+ // Converts |identifier|, a debug_identifier-formatted string, into its
+ // component fields: either a GUID and age, or signature and age. If
+ // successful, sets the relevant fields in the object, including the type
+ // field, and returns true. On error, returns false.
+ bool InitializeFromString(const string &identifier);
+
+ GUIDOrSignatureType type() const { return type_; }
+ GUID guid() const { return guid_; }
+ DWORD signature() const { return signature_; }
+ int age() const { return age_; }
+ const void *guid_or_signature_pointer() const { return &guid_; }
+
+ private:
+ GUIDOrSignatureType type_;
+
+ // An identifier contains either a 128-bit uuid or a 32-bit signature.
+ union {
+ GUID guid_;
+ DWORD signature_;
+ };
+
+ // All identifiers used here have age fields, which indicate a specific
+ // revision given a uuid or signature.
+ int age_;
+};
+
+class MSSymbolServerConverter {
+ public:
+ enum LocateResult {
+ LOCATE_FAILURE = 0,
+ LOCATE_NOT_FOUND, // Authoritative: the file is not present.
+ LOCATE_RETRY, // Transient (network?) error, try again later.
+ LOCATE_SUCCESS
+ };
+
+ // Create a new object. local_cache is the location (pathname) of a local
+ // symbol store used to hold downloaded and converted symbol files. This
+ // directory will be created by LocateSymbolFile when it successfully
+ // retrieves a symbol file. symbol_servers contains a list of locations (URLs
+ // or pathnames) of the upstream symbol server stores, given in order of
+ // preference, with the first string in the vector identifying the first
+ // store to try. The vector must contain at least one string. None of the
+ // strings passed to this constructor may contain asterisk ('*') or semicolon
+ // (';') characters, as the symbol engine uses these characters as separators.
+ MSSymbolServerConverter(const string &local_cache,
+ const vector<string> &symbol_servers);
+
+ // Locates the PE file (DLL or EXE) specified by the identifying information
+ // in |missing|, by checking the symbol stores identified when the object
+ // was created. When returning LOCATE_SUCCESS, pe_file is set to
+ // the pathname of the decompressed PE file as it is stored in the
+ // local cache.
+ LocateResult LocatePEFile(const MissingSymbolInfo &missing, string *pe_file);
+
+ // Locates the symbol file specified by the identifying information in
+ // |missing|, by checking the symbol stores identified when the object
+ // was created. When returning LOCATE_SUCCESS, symbol_file is set to
+ // the pathname of the decompressed symbol file as it is stored in the
+ // local cache.
+ LocateResult LocateSymbolFile(const MissingSymbolInfo &missing,
+ string *symbol_file);
+
+ // Calls LocateSymbolFile and converts the returned symbol file to the
+ // dumped-symbol format, storing it adjacent to the symbol file. The
+ // only conversion supported is from pdb files. Returns the return
+ // value of LocateSymbolFile, or if LocateSymbolFile succeeds but
+ // conversion fails, returns LOCATE_FAILURE. The pathname to the
+ // pdb file and to the converted symbol file are returned in
+ // |converted_symbol_file|, |symbol_file|, and |pe_file|. |symbol_file| and
+ // |pe_file| are optional and may be NULL. If only the converted symbol file
+ // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate
+ // that the original symbol file (pdb) and executable file (exe, dll) should
+ // be deleted after conversion.
+ LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing,
+ bool keep_symbol_file,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ 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
+ // the symbol stores identified when the object was created. When
+ // returning LOCATE_SUCCESS, file_name is set to the pathname of the
+ // decompressed PDB or PE file file as it is stored in the local cache.
+ LocateResult LocateFile(const string &debug_or_code_file,
+ const string &debug_or_code_id,
+ const string &version, string *file_name);
+
+ // Called by various SymSrv functions to report status as progress is made
+ // and to allow the callback to influence processing. Messages sent to this
+ // callback can be used to distinguish between the various failure modes
+ // that SymFindFileInPath might encounter.
+ static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data,
+ ULONG64 context);
+
+ // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate
+ // symbol file is located, when it's present in the local cache.
+ // SymFindFileInPath actually seems to accept NULL for a callback function
+ // and behave properly for our needs in that case, but the documentation
+ // doesn't mention it, so this little callback is provided.
+ static BOOL CALLBACK SymFindFileInPathCallback(const char *filename,
+ void *context);
+
+ // The search path used by SymSrv, built based on the arguments to the
+ // constructor.
+ string symbol_path_;
+
+ // SymCallback will set at least one of these failure variables if
+ // SymFindFileInPath fails for an expected reason.
+ bool fail_dns_; // DNS failures (fail_not_found_ will also be set).
+ bool fail_timeout_; // Timeouts (fail_not_found_ will also be set).
+ bool fail_not_found_; // The file could not be found. If this is the only
+ // fail_* member set, then it is authoritative.
+};
+
+} // namespace google_breakpad
+
+#endif // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
new file mode 100644
index 0000000000..ee1263a147
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Purify|Win32">
+ <Configuration>Purify</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Purify|x64">
+ <Configuration>Purify</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1463C4CD-23FC-4DE9-BFDE-283338200157}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ms_symbol_server_converter</RootNamespace>
+ <IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
+ <PropertyGroup Label="Configuration">
+ <CharacterSet>Unicode</CharacterSet>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
+ <ImportGroup Label="ExtensionSettings"/>
+ <ImportGroup Label="PropertySheets">
+ <Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros"/>
+ <PropertyGroup>
+ <ExecutablePath>$(ExecutablePath);$(MSBuildProjectDirectory)\..\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\..\third_party\python_26\</ExecutablePath>
+ <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Purify|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Purify|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <TargetName>$(ProjectName)</TargetName>
+ <TargetPath>$(OutDir)lib\$(ProjectName)$(TargetExt)</TargetPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Purify|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Purify|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <EnableCOMDATFolding>false</EnableCOMDATFolding>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <OmitFramePointers>true</OmitFramePointers>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <StringPooling>true</StringPooling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <None Include="ms_symbol_server_converter.gyp"/>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="ms_symbol_server_converter.cc"/>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
+ <ImportGroup Label="ExtensionTargets"/>
+</Project>
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd
new file mode 100644
index 0000000000..5464a61ed7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd
@@ -0,0 +1,33 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Please, make sure to run this in an Elevated Command Prompt.
+REM Usage:
+REM configure.cmd
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Register msdia140.dll.
+REM ******************************************************************
+SET MSG=Failed to register msdia140.dll. Make sure to run this in elevated command prompt.
+%systemroot%\SysWoW64\regsvr32.exe /s msdia140.dll & if errorlevel 1 echo %MSG% & goto :fail
+
+:success
+echo Configuration was successful.
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc
new file mode 100644
index 0000000000..5b70903a4d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc
@@ -0,0 +1,807 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma comment(lib, "winhttp.lib")
+#pragma comment(lib, "wininet.lib")
+#pragma comment(lib, "diaguids.lib")
+#pragma comment(lib, "imagehlp.lib")
+
+#include <cassert>
+#include <cstdio>
+#include <ctime>
+#include <map>
+#include <regex>
+#include <string>
+#include <vector>
+
+#include "tools/windows/converter_exe/escaping.h"
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/tokenizer.h"
+#include "common/windows/http_upload.h"
+#include "common/windows/string_utils-inl.h"
+#include "tools/windows/converter/ms_symbol_server_converter.h"
+
+using strings::WebSafeBase64Unescape;
+using strings::WebSafeBase64Escape;
+
+namespace {
+
+using std::map;
+using std::string;
+using std::vector;
+using std::wstring;
+using crash::HTTPDownload;
+using crash::Tokenizer;
+using google_breakpad::HTTPUpload;
+using google_breakpad::MissingSymbolInfo;
+using google_breakpad::MSSymbolServerConverter;
+using google_breakpad::WindowsStringUtils;
+
+const char *kMissingStringDelimiters = "|";
+const char *kLocalCachePath = "c:\\symbols";
+const char *kNoExeMSSSServer = "http://msdl.microsoft.com/download/symbols/";
+
+// Windows stdio doesn't do line buffering. Use this function to flush after
+// writing to stdout and stderr so that a log will be available if the
+// converter crashes.
+static int FprintfFlush(FILE *file, const char *format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ int retval = vfprintf(file, format, arguments);
+ va_end(arguments);
+ fflush(file);
+ return retval;
+}
+
+static string CurrentDateAndTime() {
+ const string kUnknownDateAndTime = R"(????-??-?? ??:??:??)";
+
+ time_t current_time;
+ time(&current_time);
+
+ // localtime_s is safer but is only available in MSVC8. Use localtime
+ // in earlier environments.
+ struct tm *time_pointer;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ struct tm time_struct;
+ time_pointer = &time_struct;
+ if (localtime_s(time_pointer, &current_time) != 0) {
+ return kUnknownDateAndTime;
+ }
+#else // _MSC_VER >= 1400
+ time_pointer = localtime(&current_time);
+ if (!time_pointer) {
+ return kUnknownDateAndTime;
+ }
+#endif // _MSC_VER >= 1400
+
+ char buffer[256];
+ if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_pointer)) {
+ return kUnknownDateAndTime;
+ }
+
+ return string(buffer);
+}
+
+// ParseMissingString turns |missing_string| into a MissingSymbolInfo
+// structure. It returns true on success, and false if no such conversion
+// is possible.
+static bool ParseMissingString(const string &missing_string,
+ MissingSymbolInfo *missing_info) {
+ assert(missing_info);
+
+ vector<string> tokens;
+ Tokenizer::Tokenize(kMissingStringDelimiters, missing_string, &tokens);
+ if (tokens.size() != 5) {
+ return false;
+ }
+
+ missing_info->debug_file = tokens[0];
+ missing_info->debug_identifier = tokens[1];
+ missing_info->version = tokens[2];
+ missing_info->code_file = tokens[3];
+ missing_info->code_identifier = tokens[4];
+
+ return true;
+}
+
+// StringMapToWStringMap takes each element in a map that associates
+// (narrow) strings to strings and converts the keys and values to wstrings.
+// Returns true on success and false on failure, printing an error message.
+static bool StringMapToWStringMap(const map<string, string> &smap,
+ map<wstring, wstring> *wsmap) {
+ assert(wsmap);
+ wsmap->clear();
+
+ for (map<string, string>::const_iterator iterator = smap.begin();
+ iterator != smap.end();
+ ++iterator) {
+ wstring key;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->first, &key)) {
+ FprintfFlush(stderr,
+ "StringMapToWStringMap: safe_mbstowcs failed for key %s\n",
+ iterator->first.c_str());
+ return false;
+ }
+
+ wstring value;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->second, &value)) {
+ FprintfFlush(stderr, "StringMapToWStringMap: safe_mbstowcs failed "
+ "for value %s\n",
+ iterator->second.c_str());
+ return false;
+ }
+
+ wsmap->insert(make_pair(key, value));
+ }
+
+ return true;
+}
+
+// MissingSymbolInfoToParameters turns a MissingSymbolInfo structure into a
+// map of parameters suitable for passing to HTTPDownload or HTTPUpload.
+// Returns true on success and false on failure, printing an error message.
+static bool MissingSymbolInfoToParameters(const MissingSymbolInfo &missing_info,
+ map<wstring, wstring> *wparameters) {
+ assert(wparameters);
+
+ map<string, string> parameters;
+ string encoded_param;
+ // Indicate the params are encoded.
+ parameters["encoded"] = "true"; // The string value here does not matter.
+
+ WebSafeBase64Escape(missing_info.code_file, &encoded_param);
+ parameters["code_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.code_identifier, &encoded_param);
+ parameters["code_identifier"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_file, &encoded_param);
+ parameters["debug_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_identifier, &encoded_param);
+ parameters["debug_identifier"] = encoded_param;
+
+ if (!missing_info.version.empty()) {
+ // The version is optional.
+ WebSafeBase64Escape(missing_info.version, &encoded_param);
+ parameters["version"] = encoded_param;
+ }
+
+ WebSafeBase64Escape("WinSymConv", &encoded_param);
+ parameters["product"] = encoded_param;
+
+ if (!StringMapToWStringMap(parameters, wparameters)) {
+ // StringMapToWStringMap will have printed an error.
+ return false;
+ }
+
+ return true;
+}
+
+// UploadSymbolFile sends |converted_file| as identified by |missing_info|
+// to the symbol server rooted at |upload_symbol_url|. Returns true on
+// success and false on failure, printing an error message.
+static bool UploadSymbolFile(const wstring &upload_symbol_url,
+ const MissingSymbolInfo &missing_info,
+ const string &converted_file) {
+ map<wstring, wstring> parameters;
+ if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
+ // MissingSymbolInfoToParameters or a callee will have printed an error.
+ return false;
+ }
+
+ wstring converted_file_w;
+
+ if (!WindowsStringUtils::safe_mbstowcs(converted_file, &converted_file_w)) {
+ FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
+ converted_file.c_str());
+ return false;
+ }
+ map<wstring, wstring> files;
+ files[L"symbol_file"] = converted_file_w;
+
+ FprintfFlush(stderr, "Uploading %s\n", converted_file.c_str());
+ if (!HTTPUpload::SendMultipartPostRequest(
+ upload_symbol_url, parameters,
+ files, NULL, NULL, NULL)) {
+ FprintfFlush(stderr, "UploadSymbolFile: HTTPUpload::SendRequest failed "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// SendFetchFailedPing informs the symbol server based at
+// |fetch_symbol_failure_url| that the symbol file identified by
+// |missing_info| could authoritatively not be located. Returns
+// true on success and false on failure.
+static bool SendFetchFailedPing(const wstring &fetch_symbol_failure_url,
+ const MissingSymbolInfo &missing_info) {
+ map<wstring, wstring> parameters;
+ if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
+ // MissingSymbolInfoToParameters or a callee will have printed an error.
+ return false;
+ }
+
+ string content;
+ if (!HTTPDownload::Download(fetch_symbol_failure_url,
+ &parameters,
+ &content,
+ NULL)) {
+ FprintfFlush(stderr, "SendFetchFailedPing: HTTPDownload::Download failed "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Returns true if it's safe to make an external request for the symbol
+// file described in missing_info. It's considered safe to make an
+// external request unless the symbol file's debug_file string matches
+// the given blacklist regular expression.
+// The debug_file name is used from the MissingSymbolInfo struct,
+// matched against the blacklist_regex.
+static bool SafeToMakeExternalRequest(const MissingSymbolInfo &missing_info,
+ std::regex blacklist_regex) {
+ string file_name = missing_info.debug_file;
+ // Use regex_search because we want to match substrings.
+ if (std::regex_search(file_name, blacklist_regex)) {
+ FprintfFlush(stderr, "Not safe to make external request for file %s\n",
+ file_name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Converter options derived from command line parameters.
+struct ConverterOptions {
+ ConverterOptions()
+ : report_fetch_failures(true) {
+ }
+
+ ~ConverterOptions() {
+ }
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and may
+ // have symbols for any request.
+ vector<string> full_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> full_external_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and may
+ // have symbols for any request.
+ vector<string> no_exe_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> no_exe_external_msss_servers;
+
+ // Temporary local storage for symbols.
+ string local_cache_path;
+
+ // URL for uploading symbols.
+ wstring upload_symbols_url;
+
+ // URL to fetch list of missing symbols.
+ wstring missing_symbols_url;
+
+ // URL to report symbol fetch failure.
+ wstring fetch_symbol_failure_url;
+
+ // Are symbol fetch failures reported.
+ bool report_fetch_failures;
+
+ // File containing the list of missing symbols. Fetch failures are not
+ // reported if such file is provided.
+ string missing_symbols_file;
+
+ // Regex used to blacklist files to prevent external symbol requests.
+ // Owned and cleaned up by this struct.
+ std::regex blacklist_regex;
+
+ private:
+ // DISABLE_COPY_AND_ASSIGN
+ ConverterOptions(const ConverterOptions&);
+ ConverterOptions& operator=(const ConverterOptions&);
+};
+
+// ConverMissingSymbolFile takes a single MissingSymbolInfo structure and
+// attempts to locate it from the symbol servers provided in the
+// |options.*_msss_servers| arguments. "Full" servers are those that will be
+// queried for all symbol files; "No-EXE" servers will only be queried for
+// modules whose missing symbol data indicates are not main program executables.
+// Results will be sent to the |options.upload_symbols_url| on success or
+// |options.fetch_symbol_failure_url| on failure, and the local cache will be
+// stored at |options.local_cache_path|. Because nothing can be done even in
+// the event of a failure, this function returns no value, although it
+// may result in error messages being printed.
+static void ConvertMissingSymbolFile(const MissingSymbolInfo &missing_info,
+ const ConverterOptions &options) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: attempting %s %s %s\n",
+ time_string.c_str(),
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+
+ // The first lookup is always to internal symbol servers.
+ // Always ask the symbol servers identified as "full."
+ vector<string> msss_servers = options.full_internal_msss_servers;
+
+ // If the file is not an .exe file, also ask an additional set of symbol
+ // servers, such as Microsoft's public symbol server.
+ bool is_exe = false;
+
+ if (missing_info.code_file.length() >= 4) {
+ string code_extension =
+ missing_info.code_file.substr(missing_info.code_file.size() - 4);
+
+ // Firefox is a special case: .dll-only servers should be consulted for
+ // its symbols. This enables us to get its symbols from Mozilla's
+ // symbol server when crashes occur in Google extension code hosted by a
+ // Firefox process.
+ if (_stricmp(code_extension.c_str(), ".exe") == 0 &&
+ _stricmp(missing_info.code_file.c_str(), "firefox.exe") != 0) {
+ is_exe = true;
+ }
+ }
+
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_internal_msss_servers.begin(),
+ options.no_exe_internal_msss_servers.end());
+ }
+
+ // If there are any suitable internal symbol servers, make a request.
+ MSSymbolServerConverter::LocateResult located =
+ MSSymbolServerConverter::LOCATE_FAILURE;
+ string converted_file;
+ if (msss_servers.size() > 0) {
+ // Attempt to fetch the symbol file and convert it.
+ FprintfFlush(stderr, "Making internal request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter converter(options.local_cache_path, msss_servers);
+ located = converter.LocateAndConvertSymbolFile(missing_info,
+ false, // keep_symbol_file
+ false, // keep_pe_file
+ &converted_file,
+ NULL, // symbol_file
+ NULL); // pe_file
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, missing_info,
+ converted_file);
+ remove(converted_file.c_str());
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ FprintfFlush(stderr, "LocateResult = LOCATE_NOT_FOUND\n");
+ // The symbol file definitively did not exist. Fall through,
+ // so we can attempt an external query if it's safe to do so.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Fall through in case we should make an external request.
+ // If not, or if an external request fails in the same way,
+ // we'll leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+ } else {
+ // No suitable internal symbol servers. This is fine because the converter
+ // is mainly used for downloading and converting of external symbols.
+ }
+
+ // Make a request to an external server if the internal request didn't
+ // succeed, and it's safe to do so.
+ if (located != MSSymbolServerConverter::LOCATE_SUCCESS &&
+ SafeToMakeExternalRequest(missing_info, options.blacklist_regex)) {
+ msss_servers = options.full_external_msss_servers;
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_external_msss_servers.begin(),
+ options.no_exe_external_msss_servers.end());
+ }
+ if (msss_servers.size() > 0) {
+ FprintfFlush(stderr, "Making external request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter external_converter(options.local_cache_path,
+ msss_servers);
+ located = external_converter.LocateAndConvertSymbolFile(
+ missing_info,
+ false, // keep_symbol_file
+ false, // keep_pe_file
+ &converted_file,
+ NULL, // symbol_file
+ NULL); // pe_file
+ } else {
+ FprintfFlush(stderr, "ERROR: No suitable external symbol servers.\n");
+ }
+ }
+
+ // Final handling for this symbol file is based on the result from the
+ // external request (if performed above), or on the result from the
+ // previous internal lookup.
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, missing_info,
+ converted_file);
+ remove(converted_file.c_str());
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ // The symbol file definitively didn't exist. Inform the server.
+ // If this fails, something will print an error message indicating
+ // the cause of the failure, but there's really nothing more to
+ // do. If this succeeds, the entry should be removed from the
+ // missing symbols list.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Nothing to do but leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ FprintfFlush(stderr, "ConvertMissingSymbolFile: deferring retry "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+
+ // This is due to a bad debug file name, so fetch failed.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+}
+
+
+// Reads the contents of file |file_name| and populates |contents|.
+// Returns true on success.
+static bool ReadFile(string file_name, string *contents) {
+ char buffer[1024 * 8];
+ FILE *fp = fopen(file_name.c_str(), "rt");
+ if (!fp) {
+ return false;
+ }
+ contents->clear();
+ while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+ contents->append(buffer);
+ }
+ fclose(fp);
+ return true;
+}
+
+// ConvertMissingSymbolsList obtains a missing symbol list from
+// |options.missing_symbols_url| or |options.missing_symbols_file| and calls
+// ConvertMissingSymbolFile for each missing symbol file in the list.
+static bool ConvertMissingSymbolsList(const ConverterOptions &options) {
+ // Set param to indicate requesting for encoded response.
+ map<wstring, wstring> parameters;
+ parameters[L"product"] = L"WinSymConv";
+ parameters[L"encoded"] = L"true";
+ // Get the missing symbol list.
+ string missing_symbol_list;
+ if (!options.missing_symbols_file.empty()) {
+ if (!ReadFile(options.missing_symbols_file, &missing_symbol_list)) {
+ return false;
+ }
+ } else if (!HTTPDownload::Download(options.missing_symbols_url, &parameters,
+ &missing_symbol_list, NULL)) {
+ return false;
+ }
+
+ // Tokenize the content into a vector.
+ vector<string> missing_symbol_lines;
+ Tokenizer::Tokenize("\n", missing_symbol_list, &missing_symbol_lines);
+
+ FprintfFlush(stderr, "Found %d missing symbol files in list.\n",
+ missing_symbol_lines.size() - 1); // last line is empty.
+ int convert_attempts = 0;
+ for (vector<string>::const_iterator iterator = missing_symbol_lines.begin();
+ iterator != missing_symbol_lines.end();
+ ++iterator) {
+ // Decode symbol line.
+ const string &encoded_line = *iterator;
+ // Skip lines that are blank.
+ if (encoded_line.empty()) {
+ continue;
+ }
+
+ string line;
+ if (!WebSafeBase64Unescape(encoded_line, &line)) {
+ // If decoding fails, assume the line is not encoded.
+ // This is helpful when the program connects to a debug server without
+ // encoding.
+ line = encoded_line;
+ }
+
+ FprintfFlush(stderr, "\nLine: %s\n", line.c_str());
+
+ // Turn each element into a MissingSymbolInfo structure.
+ MissingSymbolInfo missing_info;
+ if (!ParseMissingString(line, &missing_info)) {
+ FprintfFlush(stderr, "ConvertMissingSymbols: ParseMissingString failed "
+ "for %s from %ws\n",
+ line.c_str(), options.missing_symbols_url.c_str());
+ continue;
+ }
+
+ ++convert_attempts;
+ ConvertMissingSymbolFile(missing_info, options);
+ }
+
+ // Say something reassuring, since ConvertMissingSymbolFile was never called
+ // and therefore never reported any progress.
+ if (convert_attempts == 0) {
+ string current_time = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: nothing to convert\n",
+ current_time.c_str());
+ }
+
+ return true;
+}
+
+// usage prints the usage message. It returns 1 as a convenience, to be used
+// as a return value from main.
+static int usage(const char *program_name) {
+ FprintfFlush(stderr,
+ "usage: %s [options]\n"
+ " -f <full_msss_server> MS servers to ask for all symbols\n"
+ " -n <no_exe_msss_server> same, but prevent asking for EXEs\n"
+ " -l <local_cache_path> Temporary local storage for symbols\n"
+ " -s <upload_url> URL for uploading symbols\n"
+ " -m <missing_symbols_url> URL to fetch list of missing symbols\n"
+ " -mf <missing_symbols_file> File containing the list of missing\n"
+ " symbols. Fetch failures are not\n"
+ " reported if such file is provided.\n"
+ " -t <fetch_failure_url> URL to report symbol fetch failure\n"
+ " -b <regex> Regex used to blacklist files to\n"
+ " prevent external symbol requests\n"
+ " Note that any server specified by -f or -n that starts with \\filer\n"
+ " will be treated as internal, and all others as external.\n",
+ program_name);
+
+ return 1;
+}
+
+// "Internal" servers consist only of those whose names start with
+// the literal string "\\filer\".
+static bool IsInternalServer(const string &server_name) {
+ if (server_name.find("\\\\filer\\") == 0) {
+ return true;
+ }
+ return false;
+}
+
+// Adds a server with the given name to the list of internal or external
+// servers, as appropriate.
+static void AddServer(const string &server_name,
+ vector<string> *internal_servers,
+ vector<string> *external_servers) {
+ if (IsInternalServer(server_name)) {
+ internal_servers->push_back(server_name);
+ } else {
+ external_servers->push_back(server_name);
+ }
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: starting\n", time_string.c_str());
+
+ ConverterOptions options;
+ options.report_fetch_failures = true;
+
+ // All arguments are paired.
+ if (argc % 2 != 1) {
+ return usage(argv[0]);
+ }
+
+ string blacklist_regex_str;
+ bool have_any_msss_servers = false;
+ for (int argi = 1; argi < argc; argi += 2) {
+ string option = argv[argi];
+ string value = argv[argi + 1];
+
+ if (option == "-f") {
+ AddServer(value, &options.full_internal_msss_servers,
+ &options.full_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-n") {
+ AddServer(value, &options.no_exe_internal_msss_servers,
+ &options.no_exe_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-l") {
+ if (!options.local_cache_path.empty()) {
+ return usage(argv[0]);
+ }
+ options.local_cache_path = value;
+ } else if (option == "-s") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ &options.upload_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-m") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ &options.missing_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-mf") {
+ options.missing_symbols_file = value;
+ printf("Getting the list of missing symbols from a file. Fetch failures"
+ " will not be reported.\n");
+ options.report_fetch_failures = false;
+ } else if (option == "-t") {
+ if (!WindowsStringUtils::safe_mbstowcs(
+ value,
+ &options.fetch_symbol_failure_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-b") {
+ blacklist_regex_str = value;
+ } else {
+ return usage(argv[0]);
+ }
+ }
+
+ if (blacklist_regex_str.empty()) {
+ FprintfFlush(stderr, "No blacklist specified.\n");
+ return usage(argv[0]);
+ }
+
+ // Compile the blacklist regular expression for later use.
+ options.blacklist_regex = std::regex(blacklist_regex_str.c_str(),
+ std::regex_constants::icase);
+
+ // Set the defaults. If the user specified any MSSS servers, don't use
+ // any default.
+ if (!have_any_msss_servers) {
+ AddServer(kNoExeMSSSServer, &options.no_exe_internal_msss_servers,
+ &options.no_exe_external_msss_servers);
+ }
+
+ if (options.local_cache_path.empty()) {
+ options.local_cache_path = kLocalCachePath;
+ }
+
+ if (options.upload_symbols_url.empty()) {
+ FprintfFlush(stderr, "No upload symbols URL specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.missing_symbols_url.empty() &&
+ options.missing_symbols_file.empty()) {
+ FprintfFlush(stderr, "No missing symbols URL or file specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.fetch_symbol_failure_url.empty()) {
+ FprintfFlush(stderr, "No fetch symbol failure URL specified.\n");
+ return usage(argv[0]);
+ }
+
+ FprintfFlush(stdout,
+ "# of Symbol Servers (int/ext): %d/%d full, %d/%d no_exe\n",
+ options.full_internal_msss_servers.size(),
+ options.full_external_msss_servers.size(),
+ options.no_exe_internal_msss_servers.size(),
+ options.no_exe_external_msss_servers.size());
+
+ if (!ConvertMissingSymbolsList(options)) {
+ return 1;
+ }
+
+ time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: finished\n", time_string.c_str());
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp
new file mode 100644
index 0000000000..fe443d1b40
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp
@@ -0,0 +1,57 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'converter_exe',
+ 'type': 'executable',
+ 'sources': [
+ 'converter.cc',
+ 'escaping.cc',
+ 'escaping.h',
+ 'http_client.h',
+ 'http_download.cc',
+ 'http_download.h',
+ 'tokenizer.cc',
+ 'tokenizer.h',
+ 'winhttp_client.cc',
+ 'winhttp_client.h',
+ 'wininet_client.cc',
+ 'wininet_client.h',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ '../converter/ms_symbol_server_converter.gyp:ms_symbol_server_converter',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc
new file mode 100644
index 0000000000..74a7203ab4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc
@@ -0,0 +1,757 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/escaping.h"
+
+#include <assert.h>
+
+#define kApb kAsciiPropertyBits
+
+const unsigned char kAsciiPropertyBits[256] = {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
+ 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
+};
+
+// Use !! to suppress the warning C4800 of forcing 'int' to 'bool'.
+static inline bool ascii_isspace(unsigned char c) { return !!(kApb[c] & 0x08); }
+
+///////////////////////////////////
+// scoped_array
+///////////////////////////////////
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+// scoped_array<T> is thread-compatible, and once you index into it,
+// the returned objects have only the threadsafety guarantees of T.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_array.
+ // The input parameter must be allocated with new [].
+ explicit scoped_array(C* p = NULL) : array_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // Will assert() if there is no current object, or index i is negative.
+ C& operator[](std::ptrdiff_t i) const {
+ assert(i >= 0);
+ assert(array_ != NULL);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether a scoped_array and a raw pointer refer to
+ // the same array, not just to two different but equal arrays.
+ bool operator==(const C* p) const { return array_ == p; }
+ bool operator!=(const C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_array(const scoped_array&);
+ void operator=(const scoped_array&);
+};
+
+
+///////////////////////////////////
+// Escape methods
+///////////////////////////////////
+
+namespace strings {
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+ // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+ return str->empty() ? NULL : &*str->begin();
+}
+
+int CalculateBase64EscapedLen(int input_len, bool do_padding) {
+ // these formulae were copied from comments that used to go with the base64
+ // encoding functions
+ int intermediate_result = 8 * input_len + 5;
+ assert(intermediate_result > 0); // make sure we didn't overflow
+ int len = intermediate_result / 6;
+ if (do_padding) len = ((len + 3) / 4) * 4;
+ return len;
+}
+
+// Base64Escape does padding, so this calculation includes padding.
+int CalculateBase64EscapedLen(int input_len) {
+ return CalculateBase64EscapedLen(input_len, true);
+}
+
+// ----------------------------------------------------------------------
+// int Base64Unescape() - base64 decoder
+// int Base64Escape() - base64 encoder
+// int WebSafeBase64Unescape() - Google's variation of base64 decoder
+// int WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://www.cis.ohio-state.edu/htbin/rfc/rfc2045.html for formal
+// description, but what we care about is that...
+// Take the encoded stuff in groups of 4 characters and turn each
+// character into a code 0 to 63 thus:
+// A-Z map to 0 to 25
+// a-z map to 26 to 51
+// 0-9 map to 52 to 61
+// +(- for WebSafe) maps to 62
+// /(_ for WebSafe) maps to 63
+// There will be four numbers, all less than 64 which can be represented
+// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+// Arrange the 6 digit binary numbers into three bytes as such:
+// aaaaaabb bbbbcccc ccdddddd
+// Equals signs (one or two) are used at the end of the encoded block to
+// indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
+int Base64UnescapeInternal(const char *src, int szsrc,
+ char *dest, int szdest,
+ const signed char* unbase64) {
+ static const char kPad64 = '=';
+
+ int decode = 0;
+ int destidx = 0;
+ int state = 0;
+ unsigned int ch = 0;
+ unsigned int temp = 0;
+
+ // The GET_INPUT macro gets the next input character, skipping
+ // over any whitespace, and stopping when we reach the end of the
+ // string or when we read any non-data character. The arguments are
+ // an arbitrary identifier (used as a label for goto) and the number
+ // of data bytes that must remain in the input to avoid aborting the
+ // loop.
+#define GET_INPUT(label, remain) \
+ label: \
+ --szsrc; \
+ ch = *src++; \
+ decode = unbase64[ch]; \
+ if (decode < 0) { \
+ if (ascii_isspace((char)ch) && szsrc >= remain) \
+ goto label; \
+ state = 4 - remain; \
+ break; \
+ }
+
+ // if dest is null, we're just checking to see if it's legal input
+ // rather than producing output. (I suspect this could just be done
+ // with a regexp...). We duplicate the loop so this test can be
+ // outside it instead of in every iteration.
+
+ if (dest) {
+ // This loop consumes 4 input bytes and produces 3 output bytes
+ // per iteration. We can't know at the start that there is enough
+ // data left in the string for a full iteration, so the loop may
+ // break out in the middle; if so 'state' will be set to the
+ // number of input bytes read.
+
+ while (szsrc >= 4) {
+ // We'll start by optimistically assuming that the next four
+ // bytes of the string (src[0..3]) are four good data bytes
+ // (that is, no nulls, whitespace, padding chars, or illegal
+ // chars). We need to test src[0..2] for nulls individually
+ // before constructing temp to preserve the property that we
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
+
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ // Iff any of those four characters was bad (null, illegal,
+ // whitespace, padding), then temp's high bit will be set
+ // (because unbase64[] is -1 for all bad characters).
+ //
+ // We'll back up and resort to the slower decoder, which knows
+ // how to handle those cases.
+
+ GET_INPUT(first, 4);
+ temp = decode;
+ GET_INPUT(second, 3);
+ temp = (temp << 6) | decode;
+ GET_INPUT(third, 2);
+ temp = (temp << 6) | decode;
+ GET_INPUT(fourth, 1);
+ temp = (temp << 6) | decode;
+ } else {
+ // We really did have four good data bytes, so advance four
+ // characters in the string.
+
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+
+ // temp has 24 bits of input, so write that out as three bytes.
+
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ destidx += 3;
+ }
+ } else {
+ while (szsrc >= 4) {
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ GET_INPUT(first_no_dest, 4);
+ GET_INPUT(second_no_dest, 3);
+ GET_INPUT(third_no_dest, 2);
+ GET_INPUT(fourth_no_dest, 1);
+ } else {
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+ destidx += 3;
+ }
+ }
+
+#undef GET_INPUT
+
+ // if the loop terminated because we read a bad character, return
+ // now.
+ if (decode < 0 && ch != '\0' && ch != kPad64 && !ascii_isspace((char)ch))
+ return -1;
+
+ if (ch == kPad64) {
+ // if we stopped by hitting an '=', un-read that character -- we'll
+ // look at it again when we count to check for the proper number of
+ // equals signs at the end.
+ ++szsrc;
+ --src;
+ } else {
+ // This loop consumes 1 input byte per iteration. It's used to
+ // clean up the 0-3 input bytes remaining when the first, faster
+ // loop finishes. 'temp' contains the data from 'state' input
+ // characters read by the first loop.
+ while (szsrc > 0) {
+ --szsrc;
+ ch = *src++;
+ decode = unbase64[ch];
+ if (decode < 0) {
+ if (ascii_isspace((char)ch)) {
+ continue;
+ } else if (ch == '\0') {
+ break;
+ } else if (ch == kPad64) {
+ // back up one character; we'll read it again when we check
+ // for the correct number of equals signs at the end.
+ ++szsrc;
+ --src;
+ break;
+ } else {
+ return -1;
+ }
+ }
+
+ // Each input character gives us six bits of output.
+ temp = (temp << 6) | decode;
+ ++state;
+ if (state == 4) {
+ // If we've accumulated 24 bits of output, write that out as
+ // three bytes.
+ if (dest) {
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 3;
+ state = 0;
+ temp = 0;
+ }
+ }
+ }
+
+ // Process the leftover data contained in 'temp' at the end of the input.
+ int expected_equals = 0;
+ switch (state) {
+ case 0:
+ // Nothing left over; output is a multiple of 3 bytes.
+ break;
+
+ case 1:
+ // Bad input; we have 6 bits left over.
+ return -1;
+
+ case 2:
+ // Produce one more output byte from the 12 input bits we have left.
+ if (dest) {
+ if (destidx+1 > szdest) return -1;
+ temp >>= 4;
+ dest[destidx] = (char)temp;
+ }
+ ++destidx;
+ expected_equals = 2;
+ break;
+
+ case 3:
+ // Produce two more output bytes from the 18 input bits we have left.
+ if (dest) {
+ if (destidx+2 > szdest) return -1;
+ temp >>= 2;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 2;
+ expected_equals = 1;
+ break;
+
+ default:
+ // state should have no other values at this point.
+ fprintf(stdout, "This can't happen; base64 decoder state = %d", state);
+ }
+
+ // The remainder of the string should be all whitespace, mixed with
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
+ // signs. (Always accepting 0 equals signs is a google extension
+ // not covered in the RFC.)
+
+ int equals = 0;
+ while (szsrc > 0 && *src) {
+ if (*src == kPad64)
+ ++equals;
+ else if (!ascii_isspace(*src))
+ return -1;
+ --szsrc;
+ ++src;
+ }
+
+ return (equals == 0 || equals == expected_equals) ? destidx : -1;
+}
+
+int Base64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool Base64Unescape(const char *src, int slen, string* dest) {
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // 4 characters. any leftover chars are added directly for good measure.
+ // This is documented in the base64 RFC: http://www.ietf.org/rfc/rfc3548.txt
+ const int dest_len = 3 * (slen / 4) + (slen % 4);
+
+ dest->resize(dest_len);
+
+ // We are getting the destination buffer by getting the beginning of the
+ // string and converting it into a char *.
+ const int len = Base64Unescape(src, slen,
+ string_as_array(dest), dest->size());
+ if (len < 0) {
+ return false;
+ }
+
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+
+ return true;
+}
+
+// Base64Escape
+//
+// NOTE: We have to use an unsigned type for src because code built
+// in the the /google tree treats characters as signed unless
+// otherwised specified.
+//
+// TODO(who?): Move this function to use the char* type for "src"
+int Base64EscapeInternal(const unsigned char *src, int szsrc,
+ char *dest, int szdest, const char *base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc <= 0) return 0;
+
+ char *cur_dest = dest;
+ const unsigned char *cur_src = src;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ while (szsrc > 2) { /* keep going until we have less than 24 bits */
+ if ((szdest -= 4) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[((cur_src[1] & 0x0f) << 2) + (cur_src[2] >> 6)];
+ cur_dest[3] = base64[cur_src[2] & 0x3f];
+
+ cur_dest += 4;
+ cur_src += 3;
+ szsrc -= 3;
+ }
+
+ /* now deal with the tail (<=2 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1:
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[(cur_src[0] & 0x03) << 4];
+ cur_dest += 2;
+ if (do_padding) {
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ }
+ break;
+ case 2:
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if ((szdest -= 3) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[(cur_src[1] & 0x0f) << 2];
+ cur_dest += 3;
+ if (do_padding) {
+ if ((szdest -= 1) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ }
+ break;
+ default:
+ // Should not be reached: blocks of 3 bytes are handled
+ // in the while loop before this switch statement.
+ fprintf(stderr, "Logic problem? szsrc = %d", szsrc);
+ assert(false);
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+static const char kBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char kWebSafeBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
+}
+
+void Base64Escape(const unsigned char *src, int szsrc,
+ string* dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void Base64Escape(const string& src, string* dest) {
+ Base64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), dest, true);
+}
+
+////////////////////////////////////////////////////
+// WebSafe methods
+////////////////////////////////////////////////////
+
+int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool WebSafeBase64Unescape(const char *src, int slen, string* dest) {
+ int dest_len = 3 * (slen / 4) + (slen % 4);
+ dest->clear();
+ dest->resize(dest_len);
+ int len = WebSafeBase64Unescape(src, slen, &*dest->begin(), dest->size());
+ if (len < 0) {
+ dest->clear();
+ return false;
+ }
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+ return true;
+}
+
+bool WebSafeBase64Unescape(const string& src, string* dest) {
+ return WebSafeBase64Unescape(src.data(), src.size(), dest);
+}
+
+int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
+ int szdest, bool do_padding) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest,
+ kWebSafeBase64Chars, do_padding);
+}
+
+void WebSafeBase64Escape(const unsigned char *src, int szsrc,
+ string *dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kWebSafeBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void WebSafeBase64EscapeInternal(const string& src,
+ string* dest,
+ bool do_padding) {
+ int encoded_len = CalculateBase64EscapedLen(src.size());
+ scoped_array<char> buf(new char[encoded_len]);
+ int len = WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), buf.get(),
+ encoded_len, do_padding);
+ dest->assign(buf.get(), len);
+}
+
+void WebSafeBase64Escape(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, false);
+}
+
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, true);
+}
+
+} // namespace strings
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h
new file mode 100644
index 0000000000..c8aa90b7b2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h
@@ -0,0 +1,99 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Base64 escaping methods to encode/decode strings.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+
+#include <string>
+
+namespace strings {
+
+using std::string;
+
+// ----------------------------------------------------------------------
+// Base64Escape()
+// WebSafeBase64Escape()
+// Encode "src" to "dest" using base64 encoding.
+// src is not null terminated, instead specify len.
+// 'dest' should have at least CalculateBase64EscapedLen() length.
+// RETURNS the length of dest.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
+// so that we can place the out in the URL or cookies without having
+// to escape them. It also has an extra parameter "do_padding",
+// which when set to false will prevent padding with "=".
+// ----------------------------------------------------------------------
+void Base64Escape(const string& src, string* dest);
+int Base64Escape(const unsigned char* src, int slen, char* dest, int szdest);
+// Encode src into dest with padding.
+void Base64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+int WebSafeBase64Escape(const unsigned char* src, int slen, char* dest,
+ int szdest, bool do_padding);
+// Encode src into dest web-safely without padding.
+void WebSafeBase64Escape(const string& src, string* dest);
+// Encode src into dest web-safely with padding.
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest);
+void WebSafeBase64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+// ----------------------------------------------------------------------
+// Base64Unescape()
+// WebSafeBase64Unescape()
+// Copies "src" to "dest", where src is in base64 and is written to its
+// ASCII equivalents. src is not null terminated, instead specify len.
+// I recommend that slen<szdest, but we honor szdest anyway.
+// RETURNS the length of dest, or -1 if src contains invalid chars.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'.
+// The variations that store into a string clear the string first, and
+// return false (with dest empty) if src contains invalid chars; for
+// these versions src and dest must be different strings.
+// ----------------------------------------------------------------------
+int Base64Unescape(const char* src, int slen, char* dest, int szdest);
+bool Base64Unescape(const char* src, int slen, string* dest);
+inline bool Base64Unescape(const string& src, string* dest) {
+ return Base64Unescape(src.data(), src.size(), dest);
+}
+
+
+int WebSafeBase64Unescape(const char* src, int slen, char* dest, int szdest);
+bool WebSafeBase64Unescape(const char* src, int slen, string* dest);
+bool WebSafeBase64Unescape(const string& src, string* dest);
+
+// Return the length to use for the output buffer given to the base64 escape
+// routines. Make sure to use the same value for do_padding in both.
+// This function may return incorrect results if given input_len values that
+// are extremely high, which should happen rarely.
+int CalculateBase64EscapedLen(int input_len, bool do_padding);
+// Use this version when calling Base64Escape without a do_padding arg.
+int CalculateBase64EscapedLen(int input_len);
+} // namespace strings
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h
new file mode 100644
index 0000000000..3e7aa8a764
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h
@@ -0,0 +1,96 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+#define TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+
+#include <tchar.h>
+#include <windows.h>
+#include <vector>
+
+typedef void* HttpHandle;
+
+namespace crash {
+
+// HttpClient provides an abstract layer for HTTP APIs. The actual
+// implementation can be based on either WinHttp or WinInet.
+class HttpClient {
+ public:
+ enum AccessType {
+ ACCESS_TYPE_PRECONFIG,
+ ACCESS_TYPE_DIRECT,
+ ACCESS_TYPE_PROXY,
+ };
+
+ virtual ~HttpClient() {}
+
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const = 0;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const = 0;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const = 0;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const = 0;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const = 0;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const = 0;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const = 0;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const = 0;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const = 0;
+ virtual bool Close(HttpHandle handle) const = 0;
+
+ static const DWORD kUnknownContentLength = (DWORD)-1;
+};
+
+} // namespace crash
+
+#endif // TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc
new file mode 100644
index 0000000000..5afc1ccc14
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc
@@ -0,0 +1,326 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <assert.h>
+#include <stdio.h>
+#include <Windows.h>
+#include <WinInet.h>
+
+#include <vector>
+
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/winhttp_client.h"
+#include "tools/windows/converter_exe/wininet_client.h"
+
+namespace crash {
+static const std::vector<char>::size_type kVectorChunkSize = 4096; // 4 KB
+
+using std::vector;
+
+// Class that atuo closes the contained HttpHandle when the object
+// goes out of scope.
+class AutoHttpHandle {
+ public:
+ AutoHttpHandle() : handle_(NULL) {}
+ explicit AutoHttpHandle(HttpHandle handle) : handle_(handle) {}
+ ~AutoHttpHandle() {
+ if (handle_) {
+ InternetCloseHandle(handle_);
+ }
+ }
+
+ HttpHandle get() { return handle_; }
+ HttpHandle* get_handle_addr () { return &handle_; }
+
+ private:
+ HttpHandle handle_;
+};
+
+// Template class for auto releasing the contained pointer when
+// the object goes out of scope.
+template<typename T>
+class AutoPtr {
+ public:
+ explicit AutoPtr(T* ptr) : ptr_(ptr) {}
+ ~AutoPtr() {
+ if (ptr_) {
+ delete ptr_;
+ }
+ }
+
+ T* get() { return ptr_; }
+ T* operator -> () { return ptr_; }
+
+ private:
+ T* ptr_;
+};
+
+// CheckParameters ensures that the parameters in |parameters| are safe for
+// use in an HTTP URL. Returns true if they are, false if unsafe characters
+// are present.
+static bool CheckParameters(const map<wstring, wstring> *parameters) {
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ const wstring &key = iterator->first;
+ if (key.empty()) {
+ // Disallow empty parameter names.
+ return false;
+ }
+ for (unsigned int i = 0; i < key.size(); ++i) {
+ wchar_t c = key[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+
+ const wstring &value = iterator->second;
+ for (unsigned int i = 0; i < value.size(); ++i) {
+ wchar_t c = value[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) {
+ const TCHAR* kHttpApiPolicyEnvironmentVariable = TEXT("USE_WINHTTP");
+ TCHAR buffer[2] = {0};
+ HttpClient* http_client = NULL;
+
+ if (::GetEnvironmentVariable(kHttpApiPolicyEnvironmentVariable,
+ buffer,
+ sizeof(buffer)/sizeof(buffer[0])) > 0) {
+ fprintf(stdout,
+ "Environment variable [%ws] is set, use WinHttp\n",
+ kHttpApiPolicyEnvironmentVariable);
+ http_client = CreateWinHttpClient(url);
+ if (http_client == NULL) {
+ fprintf(stderr, "WinHttpClient not created, Is the protocol HTTPS? "
+ "Fall back to WinInet API.\n");
+ }
+ } else {
+ fprintf(stderr,
+ "Environment variable [%ws] is NOT set, use WinInet API\n",
+ kHttpApiPolicyEnvironmentVariable);
+ }
+
+ if (http_client == NULL) {
+ return CreateWinInetClient(url);
+ }
+
+ return http_client;
+}
+
+// static
+bool HTTPDownload::Download(const wstring &url,
+ const map<wstring, wstring> *parameters,
+ string *content, int *status_code) {
+ assert(content);
+ AutoPtr<HttpClient> http_client(CreateHttpClient(url.c_str()));
+
+ if (!http_client.get()) {
+ fprintf(stderr, "Failed to create any http client.\n");
+ return false;
+ }
+
+ if (status_code) {
+ *status_code = 0;
+ }
+
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+ if (!http_client->CrackUrl(url.c_str(),
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetCrackUrl: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ bool secure = false;
+ if (_wcsicmp(scheme, L"https") == 0) {
+ secure = true;
+ } else if (wcscmp(scheme, L"http") != 0) {
+ fprintf(stderr,
+ "HTTPDownload::Download: scheme must be http or https for %ws\n",
+ url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle internet;
+ if (!http_client->Open(NULL, // user agent
+ HttpClient::ACCESS_TYPE_PRECONFIG,
+ NULL, // proxy name
+ NULL, // proxy bypass
+ internet.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: Open: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle connection;
+ if (!http_client->Connect(internet.get(),
+ host,
+ port,
+ connection.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetConnect: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ wstring request_string = path;
+ if (parameters) {
+ // TODO(mmentovai): escape bad characters in parameters instead of
+ // forbidding them.
+ if (!CheckParameters(parameters)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: invalid characters in parameters\n");
+ return false;
+ }
+
+ bool added_parameter = false;
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ request_string.append(added_parameter ? L"&" : L"?");
+ request_string.append(iterator->first);
+ request_string.append(L"=");
+ request_string.append(iterator->second);
+ added_parameter = true;
+ }
+ }
+
+ AutoHttpHandle request;
+ if (!http_client->OpenRequest(connection.get(),
+ L"GET",
+ request_string.c_str(),
+ NULL, // version
+ NULL, // referer
+ secure,
+ request.get_handle_addr())) {
+ fprintf(stderr,
+ "HttpClient::OpenRequest: error %lu for %ws, request: %ws\n",
+ GetLastError(), url.c_str(), request_string.c_str());
+ return false;
+ }
+
+ if (!http_client->SendRequest(request.get(), NULL, 0)) {
+ fprintf(stderr,
+ "HttpClient::SendRequest: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ if (!http_client->ReceiveResponse(request.get())) {
+ fprintf(stderr,
+ "HttpClient::ReceiveResponse: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ int http_status = 0;
+ if (!http_client->GetHttpStatusCode(request.get(), &http_status)) {
+ fprintf(stderr,
+ "HttpClient::GetHttpStatusCode: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+ if (http_status != 200) {
+ fprintf(stderr,
+ "HTTPDownload::Download: HTTP status code %d for %ws\n",
+ http_status, url.c_str());
+ return false;
+ }
+
+ DWORD content_length = 0;
+ vector<char>::size_type buffer_size = 0;
+ http_client->GetContentLength(request.get(), &content_length);
+ if (content_length == HttpClient::kUnknownContentLength) {
+ buffer_size = kVectorChunkSize;
+ } else {
+ buffer_size = content_length;
+ }
+
+ if (content_length != 0) {
+ vector<char> response_buffer = vector<char>(buffer_size+1);
+ DWORD size_read;
+ DWORD total_read = 0;
+ bool read_result;
+ do {
+ if (content_length == HttpClient::kUnknownContentLength
+ && buffer_size == total_read) {
+ // The content length wasn't specified in the response header, so we
+ // have to keep growing the buffer until we're done reading.
+ buffer_size += kVectorChunkSize;
+ response_buffer.resize(buffer_size);
+ }
+ read_result = !!http_client->ReadData(
+ request.get(),
+ &response_buffer[total_read],
+ static_cast<DWORD>(buffer_size) - total_read,
+ &size_read);
+ total_read += size_read;
+ } while (read_result && (size_read != 0));
+
+ if (!read_result) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu for %ws\n",
+ GetLastError(),
+ url.c_str());
+ return false;
+ } else if (size_read != 0) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu/%lu for %ws\n",
+ total_read,
+ content_length,
+ url.c_str());
+ return false;
+ }
+ content->assign(&response_buffer[0], total_read);
+ } else {
+ content->clear();
+ }
+ return true;
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h
new file mode 100644
index 0000000000..2d705d5ece
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h
@@ -0,0 +1,62 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+
+#include <map>
+#include <string>
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+namespace crash {
+
+using std::map;
+using std::string;
+using std::wstring;
+
+class HTTPDownload {
+ public:
+ // Retrieves the resource located at |url|, a http or https URL, via WinInet.
+ // The request is fetched with GET request; the optional |parameters| are
+ // appended to the URL. Returns true on success, placing the content of the
+ // retrieved resource in |content|. Returns false on failure. HTTP status
+ // codes other than 200 cause Download to return false. If |status_code| is
+ // supplied, it will be set to the value of the HTTP status code, if an HTTP
+ // transaction occurs. If Download fails before a transaction can occur,
+ // |status_code| will be set to 0. Any failures will result in messages
+ // being printed to stderr.
+ static bool Download(const wstring &url,
+ const map<wstring, wstring> *parameters,
+ string *content, int *status_code);
+ private:
+ static HttpClient* CreateHttpClient(const wchar_t*);
+};
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt
new file mode 100644
index 0000000000..91641fca96
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt
@@ -0,0 +1,5 @@
+msctf.pdb|6A5BABB8E88644C696530BFE3C90F32F2|6.1.7600.16385|msctf.dll|4A5BDFAA109000
+imm32.pdb|98F27BA5AEE541ECBEE00CD03AD50FEE2|6.1.7600.16385|imm32.dll|4A5BDF402e000
+amd_opencl64.pdb|3D306D0FCCB14F47AF322A5ACDF5EEA81||amd_opencl64.dll|587901FB1E000
+igd10iumd64.pdb|B2B72475BB0846D8ADE4344FAE0CCE361 ||igd10iumd64.dll|568D69FBD99000
+NvCameraWhitelisting64.pdb|3C364C4D3FBF4180B021D52D469C6DAB1||NvCameraWhitelisting64.dll|5B8ED23485000 \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes
new file mode 100644
index 0000000000..1d01dda71b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes
@@ -0,0 +1,2 @@
+See breakpad/tools/windows/converter/ms_symbol_server_converter.h for a
+description of this file's function.
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc
new file mode 100644
index 0000000000..992694cd0c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <assert.h>
+
+#include "tools/windows/converter_exe/tokenizer.h"
+
+namespace crash {
+
+// static
+void Tokenizer::Tokenize(const string &delimiters, const string &input,
+ vector<string> *output) {
+ assert(output);
+ output->clear();
+
+ string::size_type position = 0; // Where to begin looking for a delimiter
+ string::size_type new_position; // Position of found delimiter
+ string token;
+
+ while ((new_position = input.find_first_of(delimiters, position)) !=
+ string::npos) {
+ token = input.substr(position, new_position - position);
+ output->push_back(token);
+
+ // Next time, begin looking right after this delimiter.
+ position = new_position + 1;
+ }
+
+ // There are no more delimiters in the string. Take everything from the
+ // final delimiter up to the end of the string as a token. This may be
+ // an empty string.
+ token = input.substr(position);
+ output->push_back(token);
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h
new file mode 100644
index 0000000000..f4bbcfd0e8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h
@@ -0,0 +1,51 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+
+#include <string>
+#include <vector>
+
+namespace crash {
+
+using std::string;
+using std::vector;
+
+class Tokenizer {
+ public:
+ // Splits |input| into a series of tokens delimited in the input string by
+ // any of the characters in |delimiters|. The tokens are passed back in the
+ // |output| vector.
+ static void Tokenize(const string &delimiters, const string &input,
+ vector<string> *output);
+};
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc
new file mode 100644
index 0000000000..8a8ade3b6c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc
@@ -0,0 +1,307 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winhttp.h>
+#include <vector>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinHttpClient : public HttpClient {
+ public:
+ virtual ~WinHttpClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinHttpClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::WinHttpCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinHttpClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::WinHttpOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+
+ return !!(*session_handle);
+}
+
+bool WinHttpClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect.
+ *connection_handle = FromHINTERNET(::WinHttpConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL));
+ return !!(*connection_handle);
+}
+
+bool WinHttpClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+ assert(request_handle);
+
+ *request_handle = FromHINTERNET(::WinHttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ is_secure ? WINHTTP_FLAG_SECURE : 0));
+ return !!(*request_handle);
+}
+
+bool WinHttpClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::WinHttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0,
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
+ NULL);
+}
+
+bool WinHttpClient::ReceiveResponse(HttpHandle request_handle) const {
+ assert(request_handle);
+
+ return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), NULL);
+}
+
+bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_STATUS_CODE,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void *>(&http_status_string),
+ &http_status_string_size, 0)) {
+ return false;
+ }
+
+ *status_code = static_cast<DWORD>(_tcstol(http_status_string, NULL, 10));
+ return true;
+}
+
+bool WinHttpClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11] = {0};
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_CONTENT_LENGTH,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void *>(&content_length_string),
+ &content_length_string_size, 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length =
+ static_cast<DWORD>(wcstol(content_length_string, NULL, 10));
+ }
+ return true;
+}
+
+bool WinHttpClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::WinHttpReadData(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinHttpClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::WinHttpCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinHttpClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
+ case ACCESS_TYPE_DIRECT:
+ return WINHTTP_ACCESS_TYPE_NO_PROXY;
+ case ACCESS_TYPE_PROXY:
+ return WINHTTP_ACCESS_TYPE_NAMED_PROXY;
+ }
+}
+
+
+HINTERNET WinHttpClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinHttpClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinHttpClient(const TCHAR* url) {
+ assert(url);
+
+ internal::WinHttpClient winhttp;
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+
+ if (!winhttp.CrackUrl(url,
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ return NULL;
+ }
+
+ if (_wcsicmp(scheme, L"https") == 0) {
+ // Winhttp under WINE doesn't support wildcard certificates, so avoid
+ // to use it if the scheme is https. The caller should fall back to
+ // use wininet if NULL is returned.
+ return NULL;
+ }
+
+ return new internal::WinHttpClient();
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h
new file mode 100644
index 0000000000..819d610f1c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinHttpClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc
new file mode 100644
index 0000000000..3e542db25f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc
@@ -0,0 +1,278 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/wininet_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wininet.h>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinInetClient : public HttpClient {
+ public:
+ virtual ~WinInetClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinInetClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::InternetCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinInetClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::InternetOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+ return !!(*session_handle);
+}
+
+bool WinInetClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect. Always uses http service.
+ *connection_handle = FromHINTERNET(::InternetConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL,
+ NULL,
+ INTERNET_SERVICE_HTTP,
+ 0,
+ 0));
+ return !!(*connection_handle);
+}
+
+bool WinInetClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+
+ *request_handle = FromHINTERNET(::HttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ NULL,
+ is_secure ? INTERNET_FLAG_SECURE : 0,
+ NULL));
+ return !!(*request_handle);
+}
+
+bool WinInetClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::HttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0);
+}
+
+bool WinInetClient::ReceiveResponse(HttpHandle) const {
+ return true;
+}
+
+bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ assert(request_handle);
+
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_STATUS_CODE,
+ static_cast<void *>(&http_status_string),
+ &http_status_string_size,
+ 0)) {
+ return false;
+ }
+
+ *status_code = _tcstol(http_status_string, NULL, 10);
+ return true;
+}
+
+bool WinInetClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11];
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_CONTENT_LENGTH,
+ static_cast<void *>(&content_length_string),
+ &content_length_string_size,
+ 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length = wcstol(content_length_string, NULL, 10);
+ }
+ return true;
+}
+
+bool WinInetClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::InternetReadFile(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinInetClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::InternetCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinInetClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return INTERNET_OPEN_TYPE_PRECONFIG;
+ case ACCESS_TYPE_DIRECT:
+ return INTERNET_OPEN_TYPE_DIRECT;
+ case ACCESS_TYPE_PROXY:
+ return INTERNET_OPEN_TYPE_PROXY;
+ }
+}
+
+HINTERNET WinInetClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinInetClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinInetClient(const TCHAR*) {
+ return new internal::WinInetClient();
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h
new file mode 100644
index 0000000000..bd04b605dc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinInetClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd
new file mode 100644
index 0000000000..bea84b589f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd
@@ -0,0 +1,86 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Usage:
+REM winsymconv
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+SET DBGHELP_WINHTTP=
+SET USE_WINHTTP=
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Make sure the symbol file directory exists
+REM ******************************************************************
+SET SYMBOL_DIR=%SCRIPT_LOCATION%symbol
+if NOT EXIST %SYMBOL_DIR% MKDIR %SYMBOL_DIR%
+if NOT EXIST %SYMBOL_DIR% echo Failed to create directory '%SYMBOL_DIR%' & goto :fail
+
+:restart
+
+REM ******************************************************************
+REM Convert missing Windows symbols on the staging instance.
+REM ******************************************************************
+echo Converting missing Windows symbols on staging instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/staging_symbol ^
+ -m https://clients2.google.com/cr/staging_symbol/missingsymbols ^
+ -t https://clients2.google.com/cr/staging_symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_staging.txt
+
+REM ******************************************************************
+REM Convert missing Windows symbols on the production instance.
+REM ******************************************************************
+echo Converting missing Windows symbols on production instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/symbol ^
+ -m https://clients2.google.com/cr/symbol/missingsymbols ^
+ -t https://clients2.google.com/cr/symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_prod.txt
+
+REM ******************************************************************
+REM Sleep for 5 minutes ...
+REM ******************************************************************
+echo Sleeping for 5 minutes ...
+
+%SCRIPT_LOCATION%sleep.exe 300
+
+REM ******************************************
+REM Restart work loop ...
+REM ******************************************
+goto :restart
+
+:success
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd
new file mode 100644
index 0000000000..c177706608
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd
@@ -0,0 +1,72 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Usage:
+REM winsymconv_test
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+SET DBGHELP_WINHTTP=
+SET USE_WINHTTP=
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Make sure the symbol file directory exists
+REM ******************************************************************
+SET SYMBOL_DIR=%SCRIPT_LOCATION%symbol
+if NOT EXIST %SYMBOL_DIR% MKDIR %SYMBOL_DIR%
+if NOT EXIST %SYMBOL_DIR% echo Failed to create directory '%SYMBOL_DIR%' & goto :fail
+
+REM ******************************************************************
+REM Testing on the staging instance.
+REM ******************************************************************
+echo Testing on the staging instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/staging_symbol ^
+ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^
+ -t https://clients2.google.com/cr/staging_symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_staging.txt
+
+REM ******************************************************************
+REM Testing on the production instance.
+REM ******************************************************************
+echo Testing on the production instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/symbol ^
+ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^
+ -t https://clients2.google.com/cr/symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_prod.txt
+
+:success
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
new file mode 100644
index 0000000000..5b7d177753
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Windows utility to dump the line number data from a pdb file to
+// a text-based format that we can use from the minidump processor.
+
+#include <stdio.h>
+#include <wchar.h>
+
+#include <string>
+
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/pe_source_line_writer.h"
+
+using std::wstring;
+using google_breakpad::PDBSourceLineWriter;
+using google_breakpad::PESourceLineWriter;
+using std::unique_ptr;
+
+int wmain(int argc, wchar_t **argv) {
+ bool success;
+ if (argc == 2) {
+ PDBSourceLineWriter pdb_writer;
+ if (!pdb_writer.Open(wstring(argv[1]), PDBSourceLineWriter::ANY_FILE)) {
+ fprintf(stderr, "Open failed.\n");
+ return 1;
+ }
+ success = pdb_writer.WriteSymbols(stdout);
+ } else if (argc == 3 && wcscmp(argv[1], L"--pe") == 0) {
+ PESourceLineWriter pe_writer(argv[2]);
+ success = pe_writer.WriteSymbols(stdout);
+ } else {
+ fprintf(stderr, "Usage: %ws [--pe] <file.[pdb|exe|dll]>\n", argv[0]);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "--pe:\tRead debugging information from PE file and do "
+ "not attempt to locate matching PDB file.\n"
+ "\tThis is only supported for PE32+ (64 bit) PE files.\n");
+ return 1;
+ }
+
+ if (!success) {
+ fprintf(stderr, "WriteSymbols failed.\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp
new file mode 100644
index 0000000000..b815574b29
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp
@@ -0,0 +1,64 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'dump_syms',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ },
+ {
+ 'target_name': 'dump_syms_unittest',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms_unittest.cc',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/client/windows/unittests/testing.gyp:gmock',
+ '<(DEPTH)/client/windows/unittests/testing.gyp:gtest',
+ 'dump_syms',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'shell32.lib',
+ ],
+ },
+ },
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
new file mode 100644
index 0000000000..2fbe301ed8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="dump_syms"
+ ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
+ RootNamespace="dumpsyms"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; imagehlp.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; imagehlp.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\dia_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\dia_util.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\dump_syms.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject> \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc
new file mode 100644
index 0000000000..766e5c09d0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc
@@ -0,0 +1,244 @@
+// Copyright 2003 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <Windows.h>
+#include <shellapi.h>
+
+#include <string>
+#include <utility>
+
+#include "breakpad_googletest_includes.h"
+
+namespace tools {
+namespace windows {
+namespace dump_syms {
+
+namespace {
+
+// Root names of PDB and dumped symbol files to be regression tested. These are
+// specified in complexity of the resulting dumped symbol files.
+const wchar_t* kRootNames[] = {
+ // A PDB file with no OMAP data.
+ L"dump_syms_regtest",
+ // A PDB file with OMAP data for an image that has been function-level
+ // reordered.
+ L"omap_reorder_funcs",
+ // A PDB file with OMAP data for an image that had new content injected, all
+ // of it with source data.
+ L"omap_stretched_filled",
+ // A PDB file with OMAP data for an image that had new content injected, but
+ // without source data.
+ L"omap_stretched",
+ // A PDB file with OMAP data for an image that has been basic block reordered.
+ L"omap_reorder_bbs",
+ // A 64bit PDB file with no OMAP data.
+ L"dump_syms_regtest64",
+};
+
+const wchar_t* kPEOnlyRootNames[] = {
+ L"pe_only_symbol_test",
+};
+
+void TrimLastComponent(const std::wstring& path,
+ std::wstring* trimmed,
+ std::wstring* component) {
+ size_t len = path.size();
+ while (len > 0 && path[len - 1] != '\\')
+ --len;
+
+ if (component != NULL)
+ component->assign(path.c_str() + len, path.c_str() + path.size());
+
+ while (len > 0 && path[len - 1] == '\\')
+ --len;
+
+ if (trimmed != NULL)
+ trimmed->assign(path.c_str(), len);
+}
+
+// Get the directory of the current executable.
+bool GetSelfDirectory(std::wstring* self_dir) {
+ std::wstring command_line = GetCommandLineW();
+
+ int num_args = 0;
+ wchar_t** args = NULL;
+ args = ::CommandLineToArgvW(command_line.c_str(), &num_args);
+ if (args == NULL)
+ return false;
+
+ *self_dir = args[0];
+ TrimLastComponent(*self_dir, self_dir, NULL);
+
+ return true;
+}
+
+void RunCommand(const std::wstring& command_line,
+ std::string* stdout_string) {
+ // Create a PIPE for the child process stdout.
+ HANDLE child_stdout_read = 0;
+ HANDLE child_stdout_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdout = {};
+ sec_attr_stdout.nLength = sizeof(sec_attr_stdout);
+ sec_attr_stdout.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdout_read, &child_stdout_write,
+ &sec_attr_stdout, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdout_read, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Create a PIPE for the child process stdin.
+ HANDLE child_stdin_read = 0;
+ HANDLE child_stdin_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdin = {};
+ sec_attr_stdin.nLength = sizeof(sec_attr_stdin);
+ sec_attr_stdin.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdin_read, &child_stdin_write,
+ &sec_attr_stdin, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdin_write, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Startup the child.
+ STARTUPINFO startup_info = {};
+ PROCESS_INFORMATION process_info = {};
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.hStdError = NULL;
+ startup_info.hStdInput = child_stdin_read;
+ startup_info.hStdOutput = child_stdout_write;
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ ASSERT_TRUE(::CreateProcessW(NULL, (LPWSTR)command_line.c_str(), NULL, NULL,
+ TRUE, 0, NULL, NULL,
+ &startup_info, &process_info));
+
+ // Collect the output.
+ ASSERT_TRUE(::CloseHandle(child_stdout_write));
+ char buffer[4096] = {};
+ DWORD bytes_read = 0;
+ while (::ReadFile(child_stdout_read, buffer, sizeof(buffer), &bytes_read,
+ NULL) && bytes_read > 0) {
+ stdout_string->append(buffer, bytes_read);
+ }
+
+ // Wait for the process to finish.
+ ::WaitForSingleObject(process_info.hProcess, INFINITE);
+
+ // Shut down all of our handles.
+ ASSERT_TRUE(::CloseHandle(process_info.hThread));
+ ASSERT_TRUE(::CloseHandle(process_info.hProcess));
+ ASSERT_TRUE(::CloseHandle(child_stdin_write));
+ ASSERT_TRUE(::CloseHandle(child_stdin_read));
+ ASSERT_TRUE(::CloseHandle(child_stdout_read));
+}
+
+void GetFileContents(const std::wstring& path, std::string* content) {
+ FILE* f = ::_wfopen(path.c_str(), L"rb");
+ ASSERT_TRUE(f != NULL);
+
+ char buffer[4096] = {};
+ while (true) {
+ size_t bytes_read = ::fread(buffer, 1, sizeof(buffer), f);
+ if (bytes_read == 0)
+ break;
+ content->append(buffer, bytes_read);
+ }
+}
+
+class DumpSymsRegressionTest : public testing::TestWithParam<const wchar_t *> {
+ public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+class DumpSymsPEOnlyRegressionTest : public testing::TestWithParam<const wchar_t *> {
+public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+} //namespace
+
+TEST_P(DumpSymsRegressionTest, EnsureDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring pdb_path = root_path + L".pdb";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" \"" +
+ pdb_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_CASE_P(DumpSyms, DumpSymsRegressionTest,
+ testing::ValuesIn(kRootNames));
+
+TEST_P(DumpSymsPEOnlyRegressionTest, EnsurePEOnlyDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring dll_path = root_path + L".dll";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" --pe \"" +
+ dll_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_CASE_P(PEOnlyDumpSyms, DumpSymsPEOnlyRegressionTest,
+ testing::ValuesIn(kPEOnlyRootNames));
+
+
+} // namespace dump_syms
+} // namespace windows
+} // namespace tools
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh
new file mode 100755
index 0000000000..1f20f64fd5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Release/dump_syms.exe testdata/dump_syms_regtest.pdb | \
+ tr -d '\015' > \
+ testdata/dump_syms_regtest.new
+status=$?
+
+if [ $status -ne 0 ] ; then
+ echo "FAIL, dump_syms.exe failed"
+ exit $status
+fi
+
+diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \
+ testdata/dump_syms_regtest.diff
+status=$?
+
+if [ $status -eq 0 ] ; then
+ rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new
+ echo "PASS"
+else
+ echo "FAIL, see testdata/dump_syms_regtest.[new|diff]"
+fi
+
+exit $status
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat b/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat
new file mode 100644
index 0000000000..bf18d5079d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat
@@ -0,0 +1,23 @@
+REM This batch file is meant to facilitate regenerating prebuilt binaries for
+REM the Windows tools.
+REM You MUST run it from a Visual Studio xxxx Command Prompt. To do this,
+REM navigate to:
+REM
+REM Start->Programs->Microsoft Visual Studio XXXX->Tools->
+REM Visual Studio Command Prompt
+REM
+REM Then run this batch file. It performs an SVN update, edits the
+REM README.binaries file to contain
+REM the revision number, and builds the tools. You must run 'svn commit' to
+REM commit the pending edits to the repository.
+
+pushd %~dp0
+if %VisualStudioVersion% == 14.0 set GYP_MSVS_VERSION=2015
+gyp tools_windows.gyp
+msbuild tools_windows.sln /p:Configuration=Release /t:Clean,Build
+copy Release\symupload.exe binaries\
+copy Release\dump_syms.exe binaries\
+git add binaries
+git commit -m "Built Windows binaries"
+echo Done!
+popd
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
new file mode 100644
index 0000000000..7e3029326d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
@@ -0,0 +1,394 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tool to upload an exe/dll and its associated symbols to an HTTP server.
+// The PDB file is located automatically, using the path embedded in the
+// executable. The upload is sent as a multipart/form-data POST request,
+// with the following parameters:
+// code_file: the basename of the module, e.g. "app.exe"
+// debug_file: the basename of the debugging file, e.g. "app.pdb"
+// debug_identifier: the debug file's identifier, usually consisting of
+// the guid and age embedded in the pdb, e.g.
+// "11111111BBBB3333DDDD555555555555F"
+// product: the HTTP-friendly product name, e.g. "MyApp"
+// version: the file version of the module, e.g. "1.2.3.4"
+// os: the operating system that the module was built for, always
+// "windows" in this implementation.
+// cpu: the CPU that the module was built for, typically "x86".
+// symbol_file: the contents of the breakpad-format symbol file
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <wininet.h>
+
+#include <cstdio>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/windows/string_utils-inl.h"
+
+#include "common/windows/http_upload.h"
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/symbol_collector_client.h"
+
+using std::string;
+using std::wstring;
+using std::vector;
+using std::map;
+using google_breakpad::HTTPUpload;
+using google_breakpad::SymbolCollectorClient;
+using google_breakpad::SymbolStatus;
+using google_breakpad::UploadUrlResponse;
+using google_breakpad::CompleteUploadResult;
+using google_breakpad::PDBModuleInfo;
+using google_breakpad::PDBSourceLineWriter;
+using google_breakpad::WindowsStringUtils;
+
+// Extracts the file version information for the given filename,
+// as a string, for example, "1.2.3.4". Returns true on success.
+static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
+ DWORD handle;
+ DWORD version_size = GetFileVersionInfoSize(filename, &handle);
+ if (version_size < sizeof(VS_FIXEDFILEINFO)) {
+ return false;
+ }
+
+ vector<char> version_info(version_size);
+ if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) {
+ return false;
+ }
+
+ void *file_info_buffer = NULL;
+ unsigned int file_info_length;
+ if (!VerQueryValue(&version_info[0], L"\\",
+ &file_info_buffer, &file_info_length)) {
+ return false;
+ }
+
+ // The maximum value of each version component is 65535 (0xffff),
+ // so the max length is 24, including the terminating null.
+ wchar_t ver_string[24];
+ VS_FIXEDFILEINFO *file_info =
+ reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
+ swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]),
+ L"%d.%d.%d.%d",
+ file_info->dwFileVersionMS >> 16,
+ file_info->dwFileVersionMS & 0xffff,
+ file_info->dwFileVersionLS >> 16,
+ file_info->dwFileVersionLS & 0xffff);
+
+ // remove when VC++7.1 is no longer supported
+ ver_string[sizeof(ver_string) / sizeof(ver_string[0]) - 1] = L'\0';
+
+ *version = ver_string;
+ return true;
+}
+
+// Creates a new temporary file and writes the symbol data from the given
+// exe/dll file to it. Returns the path to the temp file in temp_file_path
+// and information about the pdb in pdb_info.
+static bool DumpSymbolsToTempFile(const wchar_t *file,
+ wstring *temp_file_path,
+ PDBModuleInfo *pdb_info) {
+ google_breakpad::PDBSourceLineWriter writer;
+ // Use EXE_FILE to get information out of the exe/dll in addition to the
+ // pdb. The name and version number of the exe/dll are of value, and
+ // there's no way to locate an exe/dll given a pdb.
+ if (!writer.Open(file, PDBSourceLineWriter::EXE_FILE)) {
+ return false;
+ }
+
+ wchar_t temp_path[_MAX_PATH];
+ if (GetTempPath(_MAX_PATH, temp_path) == 0) {
+ return false;
+ }
+
+ wchar_t temp_filename[_MAX_PATH];
+ if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) {
+ return false;
+ }
+
+ FILE *temp_file = NULL;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ if (_wfopen_s(&temp_file, temp_filename, L"w") != 0)
+#else // _MSC_VER >= 1400
+ // _wfopen_s was introduced in MSVC8. Use _wfopen for earlier environments.
+ // Don't use it with MSVC8 and later, because it's deprecated.
+ if (!(temp_file = _wfopen(temp_filename, L"w")))
+#endif // _MSC_VER >= 1400
+ {
+ return false;
+ }
+
+ bool success = writer.WriteSymbols(temp_file);
+ fclose(temp_file);
+ if (!success) {
+ _wunlink(temp_filename);
+ return false;
+ }
+
+ *temp_file_path = temp_filename;
+
+ return writer.GetModuleInfo(pdb_info);
+}
+
+static bool DoSymUploadV2(
+ const wchar_t* api_url,
+ const wchar_t* api_key,
+ const wstring& debug_file,
+ const wstring& debug_id,
+ const wstring& symbol_file,
+ bool force) {
+ wstring url(api_url);
+ wstring key(api_key);
+
+ if (!force) {
+ SymbolStatus symbolStatus = SymbolCollectorClient::CheckSymbolStatus(
+ url,
+ key,
+ debug_file,
+ debug_id);
+ if (symbolStatus == SymbolStatus::Found) {
+ wprintf(L"Symbol file already exists, upload aborted."
+ L" Use \"-f\" to overwrite.\n");
+ return true;
+ }
+ else if (symbolStatus == SymbolStatus::Unknown) {
+ wprintf(L"Failed to get check for existing symbol.\n");
+ return false;
+ }
+ }
+
+ UploadUrlResponse uploadUrlResponse;
+ if (!SymbolCollectorClient::CreateUploadUrl(
+ url,
+ key,
+ &uploadUrlResponse)) {
+ wprintf(L"Failed to create upload URL.\n");
+ return false;
+ }
+
+ wstring signed_url = uploadUrlResponse.upload_url;
+ wstring upload_key = uploadUrlResponse.upload_key;
+ wstring response;
+ int response_code;
+ bool success = HTTPUpload::SendPutRequest(
+ signed_url,
+ symbol_file,
+ /* timeout = */ NULL,
+ &response,
+ &response_code);
+ if (!success) {
+ wprintf(L"Failed to send symbol file.\n");
+ wprintf(L"Response code: %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+ else if (response_code == 0) {
+ wprintf(L"Failed to send symbol file: No response code\n");
+ return false;
+ }
+ else if (response_code != 200) {
+ wprintf(L"Failed to send symbol file: Response code %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+
+ CompleteUploadResult completeUploadResult =
+ SymbolCollectorClient::CompleteUpload(
+ url,
+ key,
+ upload_key,
+ debug_file,
+ debug_id);
+ if (completeUploadResult == CompleteUploadResult::Error) {
+ wprintf(L"Failed to complete upload.\n");
+ return false;
+ }
+ else if (completeUploadResult == CompleteUploadResult::DuplicateData) {
+ wprintf(L"Uploaded file checksum matched existing file checksum,"
+ L" no change necessary.\n");
+ }
+ else {
+ wprintf(L"Successfully sent the symbol file.\n");
+ }
+
+ return true;
+}
+
+__declspec(noreturn) void printUsageAndExit() {
+ wprintf(L"Usage:\n\n"
+ L" symupload [--timeout NN] [--product product_name] ^\n"
+ L" <file.exe|file.dll> <symbol upload URL> ^\n"
+ L" [...<symbol upload URLs>]\n\n");
+ wprintf(L" - Timeout is in milliseconds, or can be 0 to be unlimited.\n");
+ wprintf(L" - product_name is an HTTP-friendly product name. It must only\n"
+ L" contain an ascii subset: alphanumeric and punctuation.\n"
+ L" This string is case-sensitive.\n\n");
+ wprintf(L"Example:\n\n"
+ L" symupload.exe --timeout 0 --product Chrome ^\n"
+ L" chrome.dll http://no.free.symbol.server.for.you\n");
+ wprintf(L"\n");
+ wprintf(L"sym-upload-v2 usage:\n"
+ L" symupload -p [-f] <file.exe|file.dll> <API-URL> <API-key>\n");
+ wprintf(L"\n");
+ wprintf(L"sym_upload_v2 Options:\n");
+ wprintf(L" <API-URL> is the sym_upload_v2 API URL.\n");
+ wprintf(L" <API-key> is a secret used to authenticate with the API.\n");
+ wprintf(L" -p:\t Use sym_upload_v2 protocol.\n");
+ wprintf(L" -f:\t Force symbol upload if already exists.\n");
+
+ exit(0);
+}
+
+int wmain(int argc, wchar_t *argv[]) {
+ const wchar_t *module;
+ const wchar_t *product = nullptr;
+ int timeout = -1;
+ int currentarg = 1;
+ bool use_sym_upload_v2 = false;
+ bool force = false;
+ const wchar_t* api_url = nullptr;
+ const wchar_t* api_key = nullptr;
+ while (argc > currentarg + 1) {
+ if (!wcscmp(L"--timeout", argv[currentarg])) {
+ timeout = _wtoi(argv[currentarg + 1]);
+ currentarg += 2;
+ continue;
+ }
+ if (!wcscmp(L"--product", argv[currentarg])) {
+ product = argv[currentarg + 1];
+ currentarg += 2;
+ continue;
+ }
+ if (!wcscmp(L"-p", argv[currentarg])) {
+ use_sym_upload_v2 = true;
+ ++currentarg;
+ continue;
+ }
+ if (!wcscmp(L"-f", argv[currentarg])) {
+ force = true;
+ ++currentarg;
+ continue;
+ }
+ break;
+ }
+
+ if (argc >= currentarg + 2)
+ module = argv[currentarg++];
+ else
+ printUsageAndExit();
+
+ wstring symbol_file;
+ PDBModuleInfo pdb_info;
+ if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) {
+ fwprintf(stderr, L"Could not get symbol data from %s\n", module);
+ return 1;
+ }
+
+ wstring code_file = WindowsStringUtils::GetBaseName(wstring(module));
+ wstring file_version;
+ // Don't make a missing version a hard error. Issue a warning, and let the
+ // server decide whether to reject files without versions.
+ if (!GetFileVersionString(module, &file_version)) {
+ fwprintf(stderr, L"Warning: Could not get file version for %s\n", module);
+ }
+
+ bool success = true;
+
+ if (use_sym_upload_v2) {
+ if (argc >= currentarg + 2) {
+ api_url = argv[currentarg++];
+ api_key = argv[currentarg++];
+
+ success = DoSymUploadV2(
+ api_url,
+ api_key,
+ pdb_info.debug_file,
+ pdb_info.debug_identifier,
+ symbol_file,
+ force);
+ } else {
+ printUsageAndExit();
+ }
+ } else {
+ map<wstring, wstring> parameters;
+ parameters[L"code_file"] = code_file;
+ parameters[L"debug_file"] = pdb_info.debug_file;
+ parameters[L"debug_identifier"] = pdb_info.debug_identifier;
+ parameters[L"os"] = L"windows"; // This version of symupload is Windows-only
+ parameters[L"cpu"] = pdb_info.cpu;
+
+ map<wstring, wstring> files;
+ files[L"symbol_file"] = symbol_file;
+
+ if (!file_version.empty()) {
+ parameters[L"version"] = file_version;
+ }
+
+ // Don't make a missing product name a hard error. Issue a warning and let
+ // the server decide whether to reject files without product name.
+ if (product) {
+ parameters[L"product"] = product;
+ }
+ else {
+ fwprintf(
+ stderr,
+ L"Warning: No product name (flag --product) was specified for %s\n",
+ module);
+ }
+
+ while (currentarg < argc) {
+ int response_code;
+ if (!HTTPUpload::SendMultipartPostRequest(argv[currentarg], parameters, files,
+ timeout == -1 ? NULL : &timeout,
+ nullptr, &response_code)) {
+ success = false;
+ fwprintf(stderr,
+ L"Symbol file upload to %s failed. Response code = %ld\n",
+ argv[currentarg], response_code);
+ }
+ currentarg++;
+ }
+ }
+
+ _wunlink(symbol_file.c_str());
+
+ if (success) {
+ wprintf(L"Uploaded breakpad symbols for windows-%s/%s/%s (%s %s)\n",
+ pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(),
+ pdb_info.debug_identifier.c_str(), code_file.c_str(),
+ file_version.c_str());
+ }
+
+ return success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp
new file mode 100644
index 0000000000..4567a4bdfd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp
@@ -0,0 +1,50 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'symupload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LargeAddressAware': '2',
+ },
+ },
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp
new file mode 100644
index 0000000000..17b88b4a7a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp
@@ -0,0 +1,46 @@
+# Copyright 2017 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+{
+ 'includes': [
+ '../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'build_all',
+ 'type': 'none',
+ 'dependencies': [
+ './converter/ms_symbol_server_converter.gyp:*',
+ './converter_exe/converter.gyp:*',
+ './dump_syms/dump_syms.gyp:*',
+ './symupload/symupload.gyp:*',
+ ],
+ },
+ ],
+}