summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/common/windows
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common/windows')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp105
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc92
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc76
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc420
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h129
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild15
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc694
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.h72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h137
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc330
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc1369
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h257
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h142
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc133
16 files changed, 0 insertions, 4093 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp b/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp
deleted file mode 100644
index c98333a34..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp
+++ /dev/null
@@ -1,105 +0,0 @@
-# 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': 'dia_sdk',
- 'type': 'none',
- 'all_dependent_settings': {
- 'include_dirs': [
- '<(DEPTH)',
- '$(VSInstallDir)/DIA SDK/include',
- ],
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalDependencies': [
- 'diaguids.lib',
- 'imagehlp.lib',
- ],
- },
- },
- 'configurations': {
- 'x86_Base': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalLibraryDirectories':
- ['$(VSInstallDir)/DIA SDK/lib'],
- },
- },
- },
- 'x64_Base': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalLibraryDirectories':
- ['$(VSInstallDir)/DIA SDK/lib/amd64'],
- },
- },
- },
- },
- },
- },
- {
- 'target_name': 'common_windows_lib',
- 'type': 'static_library',
- 'sources': [
- 'dia_util.cc',
- 'dia_util.h',
- 'guid_string.cc',
- 'guid_string.h',
- 'http_upload.cc',
- 'http_upload.h',
- 'omap.cc',
- 'omap.h',
- 'omap_internal.h',
- 'pdb_source_line_writer.cc',
- 'pdb_source_line_writer.h',
- 'string_utils.cc',
- 'string_utils-inl.h',
- ],
- 'dependencies': [
- 'dia_sdk',
- ],
- },
- {
- 'target_name': 'common_windows_unittests',
- 'type': 'executable',
- 'sources': [
- 'omap_unittest.cc',
- ],
- 'dependencies': [
- '<(DEPTH)/client/windows/unittests/testing.gyp:gmock',
- '<(DEPTH)/client/windows/unittests/testing.gyp:gtest',
- 'common_windows_lib',
- ],
- },
- ],
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc
deleted file mode 100644
index ed8cb5b65..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#include "common/windows/dia_util.h"
-
-#include <atlbase.h>
-
-namespace google_breakpad {
-
-bool FindDebugStream(const wchar_t* name,
- IDiaSession* session,
- IDiaEnumDebugStreamData** debug_stream) {
- CComPtr<IDiaEnumDebugStreams> enum_debug_streams;
- if (FAILED(session->getEnumDebugStreams(&enum_debug_streams))) {
- fprintf(stderr, "IDiaSession::getEnumDebugStreams failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumDebugStreamData> temp_debug_stream;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_debug_streams->Next(1, &temp_debug_stream, &fetched)) &&
- fetched == 1) {
- CComBSTR stream_name;
- if (FAILED(temp_debug_stream->get_name(&stream_name))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::get_name failed\n");
- return false;
- }
-
- // Found the stream?
- if (wcsncmp((LPWSTR)stream_name, name, stream_name.Length()) == 0) {
- *debug_stream = temp_debug_stream.Detach();
- return true;
- }
-
- temp_debug_stream.Release();
- }
-
- // No table was found.
- return false;
-}
-
-bool FindTable(REFIID iid, IDiaSession* session, void** table) {
- // Get the table enumerator.
- CComPtr<IDiaEnumTables> enum_tables;
- if (FAILED(session->getEnumTables(&enum_tables))) {
- fprintf(stderr, "IDiaSession::getEnumTables failed\n");
- return false;
- }
-
- // Iterate through the tables.
- CComPtr<IDiaTable> temp_table;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_tables->Next(1, &temp_table, &fetched)) &&
- fetched == 1) {
- void* temp = NULL;
- if (SUCCEEDED(temp_table->QueryInterface(iid, &temp))) {
- *table = temp;
- return true;
- }
- temp_table.Release();
- }
-
- // The table was not found.
- return false;
-}
-
-} // namespace google_breakpad \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h
deleted file mode 100644
index b9e0df2d5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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.
-
-// Utilities for loading debug streams and tables from a PDB file.
-
-#ifndef COMMON_WINDOWS_DIA_UTIL_H_
-#define COMMON_WINDOWS_DIA_UTIL_H_
-
-#include <Windows.h>
-#include <dia2.h>
-
-namespace google_breakpad {
-
-// Find the debug stream of the given |name| in the given |session|. Returns
-// true on success, false on error of if the stream does not exist. On success
-// the stream will be returned via |debug_stream|.
-bool FindDebugStream(const wchar_t* name,
- IDiaSession* session,
- IDiaEnumDebugStreamData** debug_stream);
-
-// Finds the first table implementing the COM interface with ID |iid| in the
-// given |session|. Returns true on success, false on error or if no such
-// table is found. On success the table will be returned via |table|.
-bool FindTable(REFIID iid, IDiaSession* session, void** table);
-
-// A templated version of FindTable. Finds the first table implementing type
-// |InterfaceType| in the given |session|. Returns true on success, false on
-// error or if no such table is found. On success the table will be returned via
-// |table|.
-template<typename InterfaceType>
-bool FindTable(IDiaSession* session, InterfaceType** table) {
- return FindTable(__uuidof(InterfaceType),
- session,
- reinterpret_cast<void**>(table));
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_DIA_UTIL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
deleted file mode 100644
index b7f877e66..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-
-// guid_string.cc: Convert GUIDs to strings.
-//
-// See guid_string.h for documentation.
-
-#include <wchar.h>
-
-#include "common/windows/string_utils-inl.h"
-
-#include "common/windows/guid_string.h"
-
-namespace google_breakpad {
-
-// static
-wstring GUIDString::GUIDToWString(GUID *guid) {
- wchar_t guid_string[37];
- swprintf(
- guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
- L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- 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]);
-
- // remove when VC++7.1 is no longer supported
- guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0';
-
- return wstring(guid_string);
-}
-
-// static
-wstring GUIDString::GUIDToSymbolServerWString(GUID *guid) {
- wchar_t guid_string[33];
- swprintf(
- guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
- L"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
- 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]);
-
- // remove when VC++7.1 is no longer supported
- guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0';
-
- return wstring(guid_string);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
deleted file mode 100644
index 48a5c1d37..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.
-
-// guid_string.cc: Convert GUIDs to strings.
-
-#ifndef COMMON_WINDOWS_GUID_STRING_H_
-#define COMMON_WINDOWS_GUID_STRING_H_
-
-#include <guiddef.h>
-
-#include <string>
-
-namespace google_breakpad {
-
-using std::wstring;
-
-class GUIDString {
- public:
- // Converts guid to a string in the format recommended by RFC 4122 and
- // returns the string.
- static wstring GUIDToWString(GUID *guid);
-
- // Converts guid to a string formatted as uppercase hexadecimal, with
- // no separators, and returns the string. This is the format used for
- // symbol server identifiers, although identifiers have an age tacked
- // on to the string.
- static wstring GUIDToSymbolServerWString(GUID *guid);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_GUID_STRING_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
deleted file mode 100644
index 7676bdc5a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-// 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.
-
-#include <assert.h>
-
-// Disable exception handler warnings.
-#pragma warning(disable:4530)
-
-#include <fstream>
-
-#include "common/windows/string_utils-inl.h"
-
-#include "common/windows/http_upload.h"
-
-namespace google_breakpad {
-
-using std::ifstream;
-using std::ios;
-
-static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";
-
-// Helper class which closes an internet handle when it goes away
-class HTTPUpload::AutoInternetHandle {
- public:
- explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
- ~AutoInternetHandle() {
- if (handle_) {
- InternetCloseHandle(handle_);
- }
- }
-
- HINTERNET get() { return handle_; }
-
- private:
- HINTERNET handle_;
-};
-
-// static
-bool HTTPUpload::SendRequest(const wstring &url,
- const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- int *timeout,
- wstring *response_body,
- int *response_code) {
- if (response_code) {
- *response_code = 0;
- }
-
- // TODO(bryner): support non-ASCII parameter names
- if (!CheckParameters(parameters)) {
- return false;
- }
-
- // Break up the URL and make sure we can handle it
- wchar_t scheme[16], host[256], path[256];
- URL_COMPONENTS components;
- memset(&components, 0, sizeof(components));
- components.dwStructSize = sizeof(components);
- components.lpszScheme = scheme;
- components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]);
- components.lpszHostName = host;
- components.dwHostNameLength = sizeof(host) / sizeof(host[0]);
- components.lpszUrlPath = path;
- components.dwUrlPathLength = sizeof(path) / sizeof(path[0]);
- if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
- 0, &components)) {
- return false;
- }
- bool secure = false;
- if (wcscmp(scheme, L"https") == 0) {
- secure = true;
- } else if (wcscmp(scheme, L"http") != 0) {
- return false;
- }
-
- AutoInternetHandle internet(InternetOpen(kUserAgent,
- INTERNET_OPEN_TYPE_PRECONFIG,
- NULL, // proxy name
- NULL, // proxy bypass
- 0)); // flags
- if (!internet.get()) {
- return false;
- }
-
- AutoInternetHandle connection(InternetConnect(internet.get(),
- host,
- components.nPort,
- NULL, // user name
- NULL, // password
- INTERNET_SERVICE_HTTP,
- 0, // flags
- NULL)); // context
- if (!connection.get()) {
- return false;
- }
-
- DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
- http_open_flags |= INTERNET_FLAG_NO_COOKIES;
- AutoInternetHandle request(HttpOpenRequest(connection.get(),
- L"POST",
- path,
- NULL, // version
- NULL, // referer
- NULL, // agent type
- http_open_flags,
- NULL)); // context
- if (!request.get()) {
- return false;
- }
-
- wstring boundary = GenerateMultipartBoundary();
- wstring content_type_header = GenerateRequestHeader(boundary);
- HttpAddRequestHeaders(request.get(),
- content_type_header.c_str(),
- static_cast<DWORD>(-1),
- HTTP_ADDREQ_FLAG_ADD);
-
- string request_body;
- if (!GenerateRequestBody(parameters, files, boundary, &request_body)) {
- return false;
- }
-
- if (timeout) {
- if (!InternetSetOption(request.get(),
- INTERNET_OPTION_SEND_TIMEOUT,
- timeout,
- sizeof(*timeout))) {
- fwprintf(stderr, L"Could not unset send timeout, continuing...\n");
- }
-
- if (!InternetSetOption(request.get(),
- INTERNET_OPTION_RECEIVE_TIMEOUT,
- timeout,
- sizeof(*timeout))) {
- fwprintf(stderr, L"Could not unset receive timeout, continuing...\n");
- }
- }
-
- if (!HttpSendRequest(request.get(), NULL, 0,
- const_cast<char *>(request_body.data()),
- static_cast<DWORD>(request_body.size()))) {
- return false;
- }
-
- // The server indicates a successful upload with HTTP status 200.
- wchar_t http_status[4];
- DWORD http_status_size = sizeof(http_status);
- if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
- static_cast<LPVOID>(&http_status), &http_status_size,
- 0)) {
- return false;
- }
-
- int http_response = wcstol(http_status, NULL, 10);
- if (response_code) {
- *response_code = http_response;
- }
-
- bool result = (http_response == 200);
-
- if (result) {
- result = ReadResponse(request.get(), response_body);
- }
-
- return result;
-}
-
-// static
-bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) {
- bool has_content_length_header = false;
- wchar_t content_length[32];
- DWORD content_length_size = sizeof(content_length);
- DWORD claimed_size = 0;
- string response_body;
-
- if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
- static_cast<LPVOID>(&content_length),
- &content_length_size, 0)) {
- has_content_length_header = true;
- claimed_size = wcstol(content_length, NULL, 10);
- response_body.reserve(claimed_size);
- }
-
-
- DWORD bytes_available;
- DWORD total_read = 0;
- BOOL return_code;
-
- while (((return_code = InternetQueryDataAvailable(request, &bytes_available,
- 0, 0)) != 0) && bytes_available > 0) {
- vector<char> response_buffer(bytes_available);
- DWORD size_read;
-
- return_code = InternetReadFile(request,
- &response_buffer[0],
- bytes_available, &size_read);
-
- if (return_code && size_read > 0) {
- total_read += size_read;
- response_body.append(&response_buffer[0], size_read);
- } else {
- break;
- }
- }
-
- bool succeeded = return_code && (!has_content_length_header ||
- (total_read == claimed_size));
- if (succeeded && response) {
- *response = UTF8ToWide(response_body);
- }
-
- return succeeded;
-}
-
-// static
-wstring HTTPUpload::GenerateMultipartBoundary() {
- // The boundary has 27 '-' characters followed by 16 hex digits
- static const wchar_t kBoundaryPrefix[] = L"---------------------------";
- static const int kBoundaryLength = 27 + 16 + 1;
-
- // Generate some random numbers to fill out the boundary
- int r0 = rand();
- int r1 = rand();
-
- wchar_t temp[kBoundaryLength];
- swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);
-
- // remove when VC++7.1 is no longer supported
- temp[kBoundaryLength - 1] = L'\0';
-
- return wstring(temp);
-}
-
-// static
-wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
- wstring header = L"Content-Type: multipart/form-data; boundary=";
- header += boundary;
- return header;
-}
-
-// static
-bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- const wstring &boundary,
- string *request_body) {
- string boundary_str = WideToUTF8(boundary);
- if (boundary_str.empty()) {
- return false;
- }
-
- request_body->clear();
-
- // Append each of the parameter pairs as a form-data part
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; name=\"" +
- WideToUTF8(pos->first) + "\"\r\n\r\n" +
- WideToUTF8(pos->second) + "\r\n");
- }
-
- for (map<wstring, wstring>::const_iterator pos = files.begin();
- pos != files.end(); ++pos) {
- vector<char> contents;
- if (!GetFileContents(pos->second, &contents)) {
- return false;
- }
-
- // Now append the upload files as a binary (octet-stream) part
- string filename_utf8 = WideToUTF8(pos->second);
- if (filename_utf8.empty()) {
- return false;
- }
-
- string file_part_name_utf8 = WideToUTF8(pos->first);
- if (file_part_name_utf8.empty()) {
- return false;
- }
-
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; "
- "name=\"" + file_part_name_utf8 + "\"; "
- "filename=\"" + filename_utf8 + "\"\r\n");
- request_body->append("Content-Type: application/octet-stream\r\n");
- request_body->append("\r\n");
-
- if (!contents.empty()) {
- request_body->append(&(contents[0]), contents.size());
- }
- request_body->append("\r\n");
- }
- request_body->append("--" + boundary_str + "--\r\n");
- return true;
-}
-
-// static
-bool HTTPUpload::GetFileContents(const wstring &filename,
- vector<char> *contents) {
- bool rv = false;
- // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
- // wchar_t* filename, so use _wfopen directly in that case. For VC8 and
- // later, _wfopen has been deprecated in favor of _wfopen_s, which does
- // not exist in earlier versions, so let the ifstream open the file itself.
- // GCC doesn't support wide file name and opening on FILE* requires ugly
- // hacks, so fallback to multi byte file.
-#ifdef _MSC_VER
- ifstream file;
- file.open(filename.c_str(), ios::binary);
-#else // GCC
- ifstream file(WideToMBCP(filename, CP_ACP).c_str(), ios::binary);
-#endif // _MSC_VER >= 1400
- if (file.is_open()) {
- file.seekg(0, ios::end);
- std::streamoff length = file.tellg();
- // Check for loss of data when converting lenght from std::streamoff into
- // std::vector<char>::size_type
- std::vector<char>::size_type vector_size =
- static_cast<std::vector<char>::size_type>(length);
- if (static_cast<std::streamoff>(vector_size) == length) {
- contents->resize(vector_size);
- if (length != 0) {
- file.seekg(0, ios::beg);
- file.read(&((*contents)[0]), length);
- }
- rv = true;
- }
- file.close();
- }
- return rv;
-}
-
-// static
-wstring HTTPUpload::UTF8ToWide(const string &utf8) {
- if (utf8.length() == 0) {
- return wstring();
- }
-
- // compute the length of the buffer we'll need
- int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
-
- if (charcount == 0) {
- return wstring();
- }
-
- // convert
- wchar_t* buf = new wchar_t[charcount];
- MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
- wstring result(buf);
- delete[] buf;
- return result;
-}
-
-// static
-string HTTPUpload::WideToMBCP(const wstring &wide, unsigned int cp) {
- if (wide.length() == 0) {
- return string();
- }
-
- // compute the length of the buffer we'll need
- int charcount = WideCharToMultiByte(cp, 0, wide.c_str(), -1,
- NULL, 0, NULL, NULL);
- if (charcount == 0) {
- return string();
- }
-
- // convert
- char *buf = new char[charcount];
- WideCharToMultiByte(cp, 0, wide.c_str(), -1, buf, charcount,
- NULL, NULL);
-
- string result(buf);
- delete[] buf;
- return result;
-}
-
-// static
-bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const wstring &str = pos->first;
- if (str.size() == 0) {
- return false; // disallow empty parameter names
- }
- for (unsigned int i = 0; i < str.size(); ++i) {
- wchar_t c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
deleted file mode 100644
index f8d48cb1b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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.
-
-// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
-// request using wininet. It currently supports requests that contain
-// a set of string parameters (key/value pairs), and a file to upload.
-
-#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H_
-#define COMMON_WINDOWS_HTTP_UPLOAD_H_
-
-#pragma warning(push)
-// Disable exception handler warnings.
-#pragma warning(disable : 4530)
-
-#include <windows.h>
-#include <wininet.h>
-
-#include <map>
-#include <string>
-#include <vector>
-
-namespace google_breakpad {
-
-using std::string;
-using std::wstring;
-using std::map;
-using std::vector;
-
-class HTTPUpload {
- public:
- // Sends the given sets of parameters and files as a multipart POST
- // request to the given URL.
- // Each key in |files| is the name of the file part of the request
- // (i.e. it corresponds to the name= attribute on an <input type="file">.
- // Parameter names must contain only printable ASCII characters,
- // and may not contain a quote (") character.
- // Only HTTP(S) URLs are currently supported. Returns true on success.
- // If the request is successful and response_body is non-NULL,
- // the response body will be returned in response_body.
- // If response_code is non-NULL, it will be set to the HTTP response code
- // received (or 0 if the request failed before getting an HTTP response).
- static bool SendRequest(const wstring &url,
- const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- int *timeout,
- wstring *response_body,
- int *response_code);
-
- private:
- class AutoInternetHandle;
-
- // Retrieves the HTTP response. If NULL is passed in for response,
- // this merely checks (via the return value) that we were successfully
- // able to retrieve exactly as many bytes of content in the response as
- // were specified in the Content-Length header.
- static bool ReadResponse(HINTERNET request, wstring* response);
-
- // Generates a new multipart boundary for a POST request
- static wstring GenerateMultipartBoundary();
-
- // Generates a HTTP request header for a multipart form submit.
- static wstring GenerateRequestHeader(const wstring &boundary);
-
- // Given a set of parameters, a set of upload files, and a file part name,
- // generates a multipart request body string with these parameters
- // and minidump contents. Returns true on success.
- static bool GenerateRequestBody(const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- const wstring &boundary,
- string *request_body);
-
- // Fills the supplied vector with the contents of filename.
- static bool GetFileContents(const wstring &filename, vector<char> *contents);
-
- // Converts a UTF8 string to UTF16.
- static wstring UTF8ToWide(const string &utf8);
-
- // Converts a UTF16 string to UTF8.
- static string WideToUTF8(const wstring &wide) {
- return WideToMBCP(wide, CP_UTF8);
- }
-
- // Converts a UTF16 string to specified code page.
- static string WideToMBCP(const wstring &wide, unsigned int cp);
-
- // Checks that the given list of parameters has only printable
- // ASCII characters in the parameter name, and does not contain
- // any quote (") characters. Returns true if so.
- static bool CheckParameters(const map<wstring, wstring> &parameters);
-
- // No instances of this class should be created.
- // Disallow all constructors, destructors, and operator=.
- HTTPUpload();
- explicit HTTPUpload(const HTTPUpload &);
- void operator=(const HTTPUpload &);
- ~HTTPUpload();
-};
-
-} // namespace google_breakpad
-
-#pragma warning(pop)
-
-#endif // COMMON_WINDOWS_HTTP_UPLOAD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
deleted file mode 100644
index 5fcdae5a3..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-lobjs_common = [
- 'guid_string.cc',
- 'string_utils.cc',
-]
-
-subdir = 'toolkit/crashreporter/google-breakpad/src/common/windows'
-objs_common = [
- '/%s/%s' % (subdir, s) for s in lobjs_common
-]
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
deleted file mode 100644
index 554a57c2d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
+++ /dev/null
@@ -1,694 +0,0 @@
-// 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.
-
-// This contains a suite of tools for transforming symbol information when
-// when that information has been extracted from a PDB containing OMAP
-// information.
-
-// OMAP information is a lightweight description of a mapping between two
-// address spaces. It consists of two streams, each of them a vector 2-tuples.
-// The OMAPTO stream contains tuples of the form
-//
-// (RVA in transformed image, RVA in original image)
-//
-// while the OMAPFROM stream contains tuples of the form
-//
-// (RVA in original image, RVA in transformed image)
-//
-// The entries in each vector are sorted by the first value of the tuple, and
-// the lengths associated with a mapping are implicit as the distance between
-// two successive addresses in the vector.
-
-// Consider a trivial 10-byte function described by the following symbol:
-//
-// Function: RVA 0x00001000, length 10, "foo"
-//
-// Now consider the same function, but with 5-bytes of instrumentation injected
-// at offset 5. The OMAP streams describing this would look like:
-//
-// OMAPTO : [ [0x00001000, 0x00001000],
-// [0x00001005, 0xFFFFFFFF],
-// [0x0000100a, 0x00001005] ]
-// OMAPFROM: [ [0x00001000, 0x00001000],
-// [0x00001005, 0x0000100a] ]
-//
-// In this case the injected code has been marked as not originating in the
-// source image, and thus it will have no symbol information at all. However,
-// the injected code may also be associated with an original address range;
-// for example, when prepending instrumentation to a basic block the
-// instrumentation can be labelled as originating from the same source BB such
-// that symbol resolution will still find the appropriate source code line
-// number. In this case the OMAP stream would look like:
-//
-// OMAPTO : [ [0x00001000, 0x00001000],
-// [0x00001005, 0x00001005],
-// [0x0000100a, 0x00001005] ]
-// OMAPFROM: [ [0x00001000, 0x00001000],
-// [0x00001005, 0x0000100a] ]
-//
-// Suppose we asked DIA to lookup the symbol at location 0x0000100a of the
-// instrumented image. It would first run this through the OMAPTO table and
-// translate that address to 0x00001005. It would then lookup the symbol
-// at that address and return the symbol for the function "foo". This is the
-// correct result.
-//
-// However, if we query DIA for the length and address of the symbol it will
-// tell us that it has length 10 and is at RVA 0x00001000. The location is
-// correct, but the length doesn't take into account the 5-bytes of injected
-// code. Symbol resolution works (starting from an instrumented address,
-// mapping to an original address, and looking up a symbol), but the symbol
-// metadata is incorrect.
-//
-// If we dump the symbols using DIA they will have their addresses
-// appropriately transformed and reflect positions in the instrumented image.
-// However, if we try to do a lookup using those symbols resolution can fail.
-// For example, the address 0x0000100a will not map to the symbol for "foo",
-// because DIA tells us it is at location 0x00001000 (correct) with length
-// 10 (incorrect). The problem is one of order of operations: in this case
-// we're attempting symbol resolution by looking up an instrumented address
-// in the table of translated symbols.
-//
-// One way to handle this is to dump the OMAP information as part of the
-// breakpad symbols. This requires the rest of the toolchain to be aware of
-// OMAP information and to use it when present prior to performing lookup. The
-// other option is to properly transform the symbols (updating length as well as
-// position) so that resolution will work as expected for translated addresses.
-// This is transparent to the rest of the toolchain.
-
-#include "common/windows/omap.h"
-
-#include <atlbase.h>
-
-#include <algorithm>
-#include <cassert>
-#include <set>
-
-#include "common/windows/dia_util.h"
-
-namespace google_breakpad {
-
-namespace {
-
-static const wchar_t kOmapToDebugStreamName[] = L"OMAPTO";
-static const wchar_t kOmapFromDebugStreamName[] = L"OMAPFROM";
-
-// Dependending on where this is used in breakpad we sometimes get min/max from
-// windef, and other times from algorithm. To get around this we simply
-// define our own min/max functions.
-template<typename T>
-const T& Min(const T& t1, const T& t2) { return t1 < t2 ? t1 : t2; }
-template<typename T>
-const T& Max(const T& t1, const T& t2) { return t1 > t2 ? t1 : t2; }
-
-// It makes things more readable to have two different OMAP types. We cast
-// normal OMAPs into these. They must be the same size as the OMAP structure
-// for this to work, hence the static asserts.
-struct OmapOrigToTran {
- DWORD rva_original;
- DWORD rva_transformed;
-};
-struct OmapTranToOrig {
- DWORD rva_transformed;
- DWORD rva_original;
-};
-static_assert(sizeof(OmapOrigToTran) == sizeof(OMAP),
- "OmapOrigToTran must have same size as OMAP.");
-static_assert(sizeof(OmapTranToOrig) == sizeof(OMAP),
- "OmapTranToOrig must have same size as OMAP.");
-typedef std::vector<OmapOrigToTran> OmapFromTable;
-typedef std::vector<OmapTranToOrig> OmapToTable;
-
-// Used for sorting and searching through a Mapping.
-bool MappedRangeOriginalLess(const MappedRange& lhs, const MappedRange& rhs) {
- if (lhs.rva_original < rhs.rva_original)
- return true;
- if (lhs.rva_original > rhs.rva_original)
- return false;
- return lhs.length < rhs.length;
-}
-bool MappedRangeMappedLess(const MappedRange& lhs, const MappedRange& rhs) {
- if (lhs.rva_transformed < rhs.rva_transformed)
- return true;
- if (lhs.rva_transformed > rhs.rva_transformed)
- return false;
- return lhs.length < rhs.length;
-}
-
-// Used for searching through the EndpointIndexMap.
-bool EndpointIndexLess(const EndpointIndex& ei1, const EndpointIndex& ei2) {
- return ei1.endpoint < ei2.endpoint;
-}
-
-// Finds the debug stream with the given |name| in the given |session|, and
-// populates |table| with its contents. Casts the data directly into OMAP
-// structs.
-bool FindAndLoadOmapTable(const wchar_t* name,
- IDiaSession* session,
- OmapTable* table) {
- assert(name != NULL);
- assert(session != NULL);
- assert(table != NULL);
-
- CComPtr<IDiaEnumDebugStreamData> stream;
- if (!FindDebugStream(name, session, &stream))
- return false;
- assert(stream.p != NULL);
-
- LONG count = 0;
- if (FAILED(stream->get_Count(&count))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::get_Count failed for stream "
- "\"%ws\"\n", name);
- return false;
- }
-
- // Get the length of the stream in bytes.
- DWORD bytes_read = 0;
- ULONG count_read = 0;
- if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
- "length of stream \"%ws\"\n", name);
- return false;
- }
-
- // Ensure it's consistent with the OMAP data type.
- DWORD bytes_expected = count * sizeof(OmapTable::value_type);
- if (count * sizeof(OmapTable::value_type) != bytes_read) {
- fprintf(stderr, "DIA debug stream \"%ws\" has an unexpected length", name);
- return false;
- }
-
- // Read the table.
- table->resize(count);
- bytes_read = 0;
- count_read = 0;
- if (FAILED(stream->Next(count, bytes_expected, &bytes_read,
- reinterpret_cast<BYTE*>(&table->at(0)),
- &count_read))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
- "data from stream \"%ws\"\n", name);
- return false;
- }
-
- return true;
-}
-
-// This determines the original image length by looking through the segment
-// table.
-bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) {
- assert(session != NULL);
- assert(image_length != NULL);
-
- CComPtr<IDiaEnumSegments> enum_segments;
- if (!FindTable(session, &enum_segments))
- return false;
- assert(enum_segments.p != NULL);
-
- DWORD temp_image_length = 0;
- CComPtr<IDiaSegment> segment;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_segments->Next(1, &segment, &fetched)) &&
- fetched == 1) {
- assert(segment.p != NULL);
-
- DWORD rva = 0;
- DWORD length = 0;
- DWORD frame = 0;
- if (FAILED(segment->get_relativeVirtualAddress(&rva)) ||
- FAILED(segment->get_length(&length)) ||
- FAILED(segment->get_frame(&frame))) {
- fprintf(stderr, "Failed to get basic properties for IDiaSegment\n");
- return false;
- }
-
- if (frame > 0) {
- DWORD segment_end = rva + length;
- if (segment_end > temp_image_length)
- temp_image_length = segment_end;
- }
- segment.Release();
- }
-
- *image_length = temp_image_length;
- return true;
-}
-
-// Detects regions of the original image that have been removed in the
-// transformed image, and sets the 'removed' property on all mapped ranges
-// immediately preceding a gap. The mapped ranges must be sorted by
-// 'rva_original'.
-void FillInRemovedLengths(Mapping* mapping) {
- assert(mapping != NULL);
-
- // Find and fill gaps. We do this with two sweeps. We first sweep forward
- // looking for gaps. When we identify a gap we then sweep forward with a
- // second scan and set the 'removed' property for any intervals that
- // immediately precede the gap.
- //
- // Gaps are typically between two successive intervals, but not always:
- //
- // Range 1: ---------------
- // Range 2: -------
- // Range 3: -------------
- // Gap : ******
- //
- // In the above example the gap is between range 1 and range 3. A forward
- // sweep finds the gap, and a second forward sweep identifies that range 1
- // immediately precedes the gap and sets its 'removed' property.
-
- size_t fill = 0;
- DWORD rva_front = 0;
- for (size_t find = 0; find < mapping->size(); ++find) {
-#ifndef NDEBUG
- // We expect the mapped ranges to be sorted by 'rva_original'.
- if (find > 0) {
- assert(mapping->at(find - 1).rva_original <=
- mapping->at(find).rva_original);
- }
-#endif
-
- if (rva_front < mapping->at(find).rva_original) {
- // We've found a gap. Fill it in by setting the 'removed' property for
- // any affected intervals.
- DWORD removed = mapping->at(find).rva_original - rva_front;
- for (; fill < find; ++fill) {
- if (mapping->at(fill).rva_original + mapping->at(fill).length !=
- rva_front) {
- continue;
- }
-
- // This interval ends right where the gap starts. It needs to have its
- // 'removed' information filled in.
- mapping->at(fill).removed = removed;
- }
- }
-
- // Advance the front that indicates the covered portion of the image.
- rva_front = mapping->at(find).rva_original + mapping->at(find).length;
- }
-}
-
-// Builds a unified view of the mapping between the original and transformed
-// image space by merging OMAPTO and OMAPFROM data.
-void BuildMapping(const OmapData& omap_data, Mapping* mapping) {
- assert(mapping != NULL);
-
- mapping->clear();
-
- if (omap_data.omap_from.empty() || omap_data.omap_to.empty())
- return;
-
- // The names 'omap_to' and 'omap_from' are awfully confusing, so we make
- // ourselves more explicit here. This cast is only safe because the underlying
- // types have the exact same size.
- const OmapToTable& tran2orig =
- reinterpret_cast<const OmapToTable&>(omap_data.omap_to);
- const OmapFromTable& orig2tran = reinterpret_cast<const OmapFromTable&>(
- omap_data.omap_from);
-
- // Handle the range of data at the beginning of the image. This is not usually
- // specified by the OMAP data.
- if (tran2orig[0].rva_transformed > 0 && orig2tran[0].rva_original > 0) {
- DWORD header_transformed = tran2orig[0].rva_transformed;
- DWORD header_original = orig2tran[0].rva_original;
- DWORD header = Min(header_transformed, header_original);
-
- MappedRange mr = {};
- mr.length = header;
- mr.injected = header_transformed - header;
- mr.removed = header_original - header;
- mapping->push_back(mr);
- }
-
- // Convert the implied lengths to explicit lengths, and infer which content
- // has been injected into the transformed image. Injected content is inferred
- // as regions of the transformed address space that does not map back to
- // known valid content in the original image.
- for (size_t i = 0; i < tran2orig.size(); ++i) {
- const OmapTranToOrig& o1 = tran2orig[i];
-
- // This maps to content that is outside the original image, thus it
- // describes injected content. We can skip this entry.
- if (o1.rva_original >= omap_data.length_original)
- continue;
-
- // Calculate the length of the current OMAP entry. This is implicit as the
- // distance between successive |rva| values, capped at the end of the
- // original image.
- DWORD length = 0;
- if (i + 1 < tran2orig.size()) {
- const OmapTranToOrig& o2 = tran2orig[i + 1];
-
- // We expect the table to be sorted by rva_transformed.
- assert(o1.rva_transformed <= o2.rva_transformed);
-
- length = o2.rva_transformed - o1.rva_transformed;
- if (o1.rva_original + length > omap_data.length_original) {
- length = omap_data.length_original - o1.rva_original;
- }
- } else {
- length = omap_data.length_original - o1.rva_original;
- }
-
- // Zero-length entries don't describe anything and can be ignored.
- if (length == 0)
- continue;
-
- // Any gaps in the transformed address-space are due to injected content.
- if (!mapping->empty()) {
- MappedRange& prev_mr = mapping->back();
- prev_mr.injected += o1.rva_transformed -
- (prev_mr.rva_transformed + prev_mr.length);
- }
-
- MappedRange mr = {};
- mr.rva_original = o1.rva_original;
- mr.rva_transformed = o1.rva_transformed;
- mr.length = length;
- mapping->push_back(mr);
- }
-
- // Sort based on the original image addresses.
- std::sort(mapping->begin(), mapping->end(), MappedRangeOriginalLess);
-
- // Fill in the 'removed' lengths by looking for gaps in the coverage of the
- // original address space.
- FillInRemovedLengths(mapping);
-
- return;
-}
-
-void BuildEndpointIndexMap(ImageMap* image_map) {
- assert(image_map != NULL);
-
- if (image_map->mapping.size() == 0)
- return;
-
- const Mapping& mapping = image_map->mapping;
- EndpointIndexMap& eim = image_map->endpoint_index_map;
-
- // Get the unique set of interval endpoints.
- std::set<DWORD> endpoints;
- for (size_t i = 0; i < mapping.size(); ++i) {
- endpoints.insert(mapping[i].rva_original);
- endpoints.insert(mapping[i].rva_original +
- mapping[i].length +
- mapping[i].removed);
- }
-
- // Use the endpoints to initialize the secondary search structure for the
- // mapping.
- eim.resize(endpoints.size());
- std::set<DWORD>::const_iterator it = endpoints.begin();
- for (size_t i = 0; it != endpoints.end(); ++it, ++i) {
- eim[i].endpoint = *it;
- eim[i].index = mapping.size();
- }
-
- // For each endpoint we want the smallest index of any interval containing
- // it. We iterate over the intervals and update the indices associated with
- // each interval endpoint contained in the current interval. In the general
- // case of an arbitrary set of intervals this is O(n^2), but the structure of
- // OMAP data makes this O(n).
- for (size_t i = 0; i < mapping.size(); ++i) {
- EndpointIndex ei1 = { mapping[i].rva_original, 0 };
- EndpointIndexMap::iterator it1 = std::lower_bound(
- eim.begin(), eim.end(), ei1, EndpointIndexLess);
-
- EndpointIndex ei2 = { mapping[i].rva_original + mapping[i].length +
- mapping[i].removed, 0 };
- EndpointIndexMap::iterator it2 = std::lower_bound(
- eim.begin(), eim.end(), ei2, EndpointIndexLess);
-
- for (; it1 != it2; ++it1)
- it1->index = Min(i, it1->index);
- }
-}
-
-// Clips the given mapped range.
-void ClipMappedRangeOriginal(const AddressRange& clip_range,
- MappedRange* mapped_range) {
- assert(mapped_range != NULL);
-
- // The clipping range is entirely outside of the mapped range.
- if (clip_range.end() <= mapped_range->rva_original ||
- mapped_range->rva_original + mapped_range->length +
- mapped_range->removed <= clip_range.rva) {
- mapped_range->length = 0;
- mapped_range->injected = 0;
- mapped_range->removed = 0;
- return;
- }
-
- // Clip the left side.
- if (mapped_range->rva_original < clip_range.rva) {
- DWORD clip_left = clip_range.rva - mapped_range->rva_original;
- mapped_range->rva_original += clip_left;
- mapped_range->rva_transformed += clip_left;
-
- if (clip_left > mapped_range->length) {
- // The left clipping boundary entirely erases the content section of the
- // range.
- DWORD trim = clip_left - mapped_range->length;
- mapped_range->length = 0;
- mapped_range->injected -= Min(trim, mapped_range->injected);
- // We know that trim <= mapped_range->remove.
- mapped_range->removed -= trim;
- } else {
- // The left clipping boundary removes some, but not all, of the content.
- // As such it leaves the removed/injected component intact.
- mapped_range->length -= clip_left;
- }
- }
-
- // Clip the right side.
- DWORD end_original = mapped_range->rva_original + mapped_range->length;
- if (clip_range.end() < end_original) {
- // The right clipping boundary lands in the 'content' section of the range,
- // entirely clearing the injected/removed portion.
- DWORD clip_right = end_original - clip_range.end();
- mapped_range->length -= clip_right;
- mapped_range->injected = 0;
- mapped_range->removed = 0;
- return;
- } else {
- // The right clipping boundary is outside of the content, but may affect
- // the removed/injected portion of the range.
- DWORD end_removed = end_original + mapped_range->removed;
- if (clip_range.end() < end_removed)
- mapped_range->removed = clip_range.end() - end_original;
-
- DWORD end_injected = end_original + mapped_range->injected;
- if (clip_range.end() < end_injected)
- mapped_range->injected = clip_range.end() - end_original;
- }
-
- return;
-}
-
-} // namespace
-
-int AddressRange::Compare(const AddressRange& rhs) const {
- if (end() <= rhs.rva)
- return -1;
- if (rhs.end() <= rva)
- return 1;
- return 0;
-}
-
-bool GetOmapDataAndDisableTranslation(IDiaSession* session,
- OmapData* omap_data) {
- assert(session != NULL);
- assert(omap_data != NULL);
-
- CComPtr<IDiaAddressMap> address_map;
- if (FAILED(session->QueryInterface(&address_map))) {
- fprintf(stderr, "IDiaSession::QueryInterface(IDiaAddressMap) failed\n");
- return false;
- }
- assert(address_map.p != NULL);
-
- BOOL omap_enabled = FALSE;
- if (FAILED(address_map->get_addressMapEnabled(&omap_enabled))) {
- fprintf(stderr, "IDiaAddressMap::get_addressMapEnabled failed\n");
- return false;
- }
-
- if (!omap_enabled) {
- // We indicate the non-presence of OMAP data by returning empty tables.
- omap_data->omap_from.clear();
- omap_data->omap_to.clear();
- omap_data->length_original = 0;
- return true;
- }
-
- // OMAP data is present. Disable translation.
- if (FAILED(address_map->put_addressMapEnabled(FALSE))) {
- fprintf(stderr, "IDiaAddressMap::put_addressMapEnabled failed\n");
- return false;
- }
-
- // Read the OMAP streams.
- if (!FindAndLoadOmapTable(kOmapFromDebugStreamName,
- session,
- &omap_data->omap_from)) {
- return false;
- }
- if (!FindAndLoadOmapTable(kOmapToDebugStreamName,
- session,
- &omap_data->omap_to)) {
- return false;
- }
-
- // Get the lengths of the address spaces.
- if (!GetOriginalImageLength(session, &omap_data->length_original))
- return false;
-
- return true;
-}
-
-void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) {
- assert(image_map != NULL);
-
- BuildMapping(omap_data, &image_map->mapping);
- BuildEndpointIndexMap(image_map);
-}
-
-void MapAddressRange(const ImageMap& image_map,
- const AddressRange& original_range,
- AddressRangeVector* mapped_ranges) {
- assert(mapped_ranges != NULL);
-
- const Mapping& map = image_map.mapping;
-
- // Handle the trivial case of an empty image_map. This means that there is
- // no transformation to be applied, and we can simply return the original
- // range.
- if (map.empty()) {
- mapped_ranges->push_back(original_range);
- return;
- }
-
- // If we get a query of length 0 we need to handle it by using a non-zero
- // query length.
- AddressRange query_range(original_range);
- if (query_range.length == 0)
- query_range.length = 1;
-
- // Find the range of intervals that can potentially intersect our query range.
- size_t imin = 0;
- size_t imax = 0;
- {
- // The index of the earliest possible range that can affect is us done by
- // searching through the secondary indexing structure.
- const EndpointIndexMap& eim = image_map.endpoint_index_map;
- EndpointIndex q1 = { query_range.rva, 0 };
- EndpointIndexMap::const_iterator it1 = std::lower_bound(
- eim.begin(), eim.end(), q1, EndpointIndexLess);
- if (it1 == eim.end()) {
- imin = map.size();
- } else {
- // Backup to find the interval that contains our query point.
- if (it1 != eim.begin() && query_range.rva < it1->endpoint)
- --it1;
- imin = it1->index;
- }
-
- // The first range that can't possibly intersect us is found by searching
- // through the image map directly as it is already sorted by interval start
- // point.
- MappedRange q2 = { query_range.end(), 0 };
- Mapping::const_iterator it2 = std::lower_bound(
- map.begin(), map.end(), q2, MappedRangeOriginalLess);
- imax = it2 - map.begin();
- }
-
- // Find all intervals that intersect the query range.
- Mapping temp_map;
- for (size_t i = imin; i < imax; ++i) {
- MappedRange mr = map[i];
- ClipMappedRangeOriginal(query_range, &mr);
- if (mr.length + mr.injected > 0)
- temp_map.push_back(mr);
- }
-
- // If there are no intersecting ranges then the query range has been removed
- // from the image in question.
- if (temp_map.empty())
- return;
-
- // Sort based on transformed addresses.
- std::sort(temp_map.begin(), temp_map.end(), MappedRangeMappedLess);
-
- // Zero-length queries can't actually be merged. We simply output the set of
- // unique RVAs that correspond to the query RVA.
- if (original_range.length == 0) {
- mapped_ranges->push_back(AddressRange(temp_map[0].rva_transformed, 0));
- for (size_t i = 1; i < temp_map.size(); ++i) {
- if (temp_map[i].rva_transformed > mapped_ranges->back().rva)
- mapped_ranges->push_back(AddressRange(temp_map[i].rva_transformed, 0));
- }
- return;
- }
-
- // Merge any ranges that are consecutive in the mapped image. We merge over
- // injected content if it makes ranges contiguous, but we ignore any injected
- // content at the tail end of a range. This allows us to detect symbols that
- // have been lengthened by injecting content in the middle. However, it
- // misses the case where content has been injected at the head or the tail.
- // The problem is that it doesn't know whether to attribute it to the
- // preceding or following symbol. It is up to the author of the transform to
- // output explicit OMAP info in these cases to ensure full coverage of the
- // transformed address space.
- DWORD rva_begin = temp_map[0].rva_transformed;
- DWORD rva_cur_content = rva_begin + temp_map[0].length;
- DWORD rva_cur_injected = rva_cur_content + temp_map[0].injected;
- for (size_t i = 1; i < temp_map.size(); ++i) {
- if (rva_cur_injected < temp_map[i].rva_transformed) {
- // This marks the end of a continuous range in the image. Output the
- // current range and start a new one.
- if (rva_begin < rva_cur_content) {
- mapped_ranges->push_back(
- AddressRange(rva_begin, rva_cur_content - rva_begin));
- }
- rva_begin = temp_map[i].rva_transformed;
- }
-
- rva_cur_content = temp_map[i].rva_transformed + temp_map[i].length;
- rva_cur_injected = rva_cur_content + temp_map[i].injected;
- }
-
- // Output the range in progress.
- if (rva_begin < rva_cur_content) {
- mapped_ranges->push_back(
- AddressRange(rva_begin, rva_cur_content - rva_begin));
- }
-
- return;
-}
-
-} // namespace google_breakpad \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
deleted file mode 100644
index bc293afb5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.
-
-// Provides an API for mapping symbols through OMAP information, if a PDB file
-// is augmented with it. This allows breakpad to work with addresses in
-// transformed images by transforming the symbols themselves, rather than
-// transforming addresses prior to querying symbols (the way it is typically
-// done by Windows-native tools, including the DIA).
-
-#ifndef COMMON_WINDOWS_OMAP_H_
-#define COMMON_WINDOWS_OMAP_H_
-
-#include "common/windows/omap_internal.h"
-
-namespace google_breakpad {
-
-// If the given session contains OMAP data this extracts it, populating
-// |omap_data|, and then disabling automatic translation for the session.
-// OMAP data is present in the PDB if |omap_data| is not empty. This returns
-// true on success, false otherwise.
-bool GetOmapDataAndDisableTranslation(IDiaSession* dia_session,
- OmapData* omap_data);
-
-// Given raw OMAP data builds an ImageMap. This can be used to query individual
-// image ranges using MapAddressRange.
-// |omap_data|| is the OMAP data extracted from the PDB.
-// |image_map| will be populated with a description of the image mapping. If
-// |omap_data| is empty then this will also be empty.
-void BuildImageMap(const OmapData& omap_data, ImageMap* image_map);
-
-// Given an address range in the original image space determines how exactly it
-// has been tranformed.
-// |omap_data| is the OMAP data extracted from the PDB, which must not be
-// empty.
-// |original_range| is the address range in the original image being queried.
-// |mapped_ranges| will be populated with a full description of the mapping.
-// They may be disjoint in the transformed image so a vector is needed to
-// fully represent the mapping. This will be appended to if it is not
-// empty. If |omap_data| is empty then |mapped_ranges| will simply be
-// populated with a copy of |original_range| (the identity transform).
-void MapAddressRange(const ImageMap& image_map,
- const AddressRange& original_range,
- AddressRangeVector* mapped_ranges);
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_OMAP_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
deleted file mode 100644
index 3f904d7a7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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.
-
-// Declares internal implementation details for functionality in omap.h and
-// omap.cc.
-
-#ifndef COMMON_WINDOWS_OMAP_INTERNAL_H_
-#define COMMON_WINDOWS_OMAP_INTERNAL_H_
-
-#include <windows.h>
-#include <dia2.h>
-
-#include <vector>
-
-namespace google_breakpad {
-
-// The OMAP struct is defined by debughlp.h, which doesn't play nicely with
-// imagehlp.h. We simply redefine it.
-struct OMAP {
- DWORD rva;
- DWORD rvaTo;
-};
-static_assert(sizeof(OMAP) == 8, "Wrong size for OMAP structure.");
-typedef std::vector<OMAP> OmapTable;
-
-// This contains the OMAP data extracted from an image.
-struct OmapData {
- // The table of OMAP entries describing the transformation from the
- // original image to the transformed image.
- OmapTable omap_from;
- // The table of OMAP entries describing the transformation from the
- // instrumented image to the original image.
- OmapTable omap_to;
- // The length of the original untransformed image.
- DWORD length_original;
-
- OmapData() : length_original(0) { }
-};
-
-// This represents a range of addresses in an image.
-struct AddressRange {
- DWORD rva;
- DWORD length;
-
- AddressRange() : rva(0), length(0) { }
- AddressRange(DWORD rva, DWORD length) : rva(rva), length(length) { }
-
- // Returns the end address of this range.
- DWORD end() const { return rva + length; }
-
- // Addreses only compare as less-than or greater-than if they are not
- // overlapping. Otherwise, they compare equal.
- int Compare(const AddressRange& rhs) const;
- bool operator<(const AddressRange& rhs) const { return Compare(rhs) == -1; }
- bool operator>(const AddressRange& rhs) const { return Compare(rhs) == 1; }
-
- // Equality operators compare exact values.
- bool operator==(const AddressRange& rhs) const {
- return rva == rhs.rva && length == rhs.length;
- }
- bool operator!=(const AddressRange& rhs) const { return !((*this) == rhs); }
-};
-
-typedef std::vector<AddressRange> AddressRangeVector;
-
-// This represents an address range in an original image, and its corresponding
-// range in the transformed image.
-struct MappedRange {
- // An address in the original image.
- DWORD rva_original;
- // The corresponding addresses in the transformed image.
- DWORD rva_transformed;
- // The length of the address range.
- DWORD length;
- // It is possible for code to be injected into a transformed image, for which
- // there is no corresponding code in the original image. If this range of
- // transformed image is immediately followed by such injected code we maintain
- // a record of its length here.
- DWORD injected;
- // It is possible for code to be removed from the original image. This happens
- // for things like padding between blocks. There is no actual content lost,
- // but the spacing between items may be lost. This keeps track of any removed
- // content immediately following the |original| range.
- DWORD removed;
-};
-// A vector of mapped ranges is used as a more useful representation of
-// OMAP data.
-typedef std::vector<MappedRange> Mapping;
-
-// Used as a secondary search structure accompanying a Mapping.
-struct EndpointIndex {
- DWORD endpoint;
- size_t index;
-};
-typedef std::vector<EndpointIndex> EndpointIndexMap;
-
-// An ImageMap is vector of mapped ranges, plus a secondary index into it for
-// doing interval searches. (An interval tree would also work, but is overkill
-// because we don't need insertion and deletion.)
-struct ImageMap {
- // This is a description of the mapping between original and transformed
- // image, sorted by addresses in the original image.
- Mapping mapping;
- // For all interval endpoints in |mapping| this stores the minimum index of
- // an interval in |mapping| that contains the endpoint. Useful for doing
- // interval intersection queries.
- EndpointIndexMap endpoint_index_map;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_OMAP_INTERNAL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
deleted file mode 100644
index 960a33f46..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// 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.
-
-// Unittests for OMAP related functions.
-
-#include "common/windows/omap.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace google_breakpad {
-
-// Equality operators for ContainerEq. These must be outside of the anonymous
-// namespace in order for them to be found.
-bool operator==(const MappedRange& mr1, const MappedRange& mr2) {
- return mr1.rva_original == mr2.rva_original &&
- mr1.rva_transformed == mr2.rva_transformed &&
- mr1.length == mr2.length &&
- mr1.injected == mr2.injected &&
- mr1.removed == mr2.removed;
-}
-bool operator==(const EndpointIndex& ei1, const EndpointIndex& ei2) {
- return ei1.endpoint == ei2.endpoint && ei1.index == ei2.index;
-}
-
-// Pretty printers for more meaningful error messages. Also need to be outside
-// the anonymous namespace.
-std::ostream& operator<<(std::ostream& os, const MappedRange& mr) {
- os << "MappedRange(rva_original=" << mr.rva_original
- << ", rva_transformed=" << mr.rva_transformed
- << ", length=" << mr.length
- << ", injected=" << mr.injected
- << ", removed=" << mr.removed << ")";
- return os;
-}
-std::ostream& operator<<(std::ostream& os, const EndpointIndex& ei) {
- os << "EndpointIndex(endpoint=" << ei.endpoint
- << ", index=" << ei.index << ")";
- return os;
-}
-std::ostream& operator<<(std::ostream& os, const AddressRange& ar) {
- os << "AddressRange(rva=" << ar.rva << ", length=" << ar.length << ")";
- return os;
-}
-
-namespace {
-
-OMAP CreateOmap(DWORD rva, DWORD rvaTo) {
- OMAP o = { rva, rvaTo };
- return o;
-}
-
-MappedRange CreateMappedRange(DWORD rva_original,
- DWORD rva_transformed,
- DWORD length,
- DWORD injected,
- DWORD removed) {
- MappedRange mr = { rva_original, rva_transformed, length, injected, removed };
- return mr;
-}
-
-EndpointIndex CreateEndpointIndex(DWORD endpoint, size_t index) {
- EndpointIndex ei = { endpoint, index };
- return ei;
-}
-
-// (C is removed)
-// Original : A B C D E F G H
-// Transformed: A B D F E * H1 G1 G2 H2
-// (* is injected, G is copied, H is split)
-// A is implied.
-
-// Layout of the original image.
-const AddressRange B(100, 15);
-const AddressRange C(B.end(), 10);
-const AddressRange D(C.end(), 25);
-const AddressRange E(D.end(), 10);
-const AddressRange F(E.end(), 40);
-const AddressRange G(F.end(), 3);
-const AddressRange H(G.end(), 7);
-
-// Layout of the transformed image.
-const AddressRange Bt(100, 15);
-const AddressRange Dt(Bt.end(), 20); // D is shortened.
-const AddressRange Ft(Dt.end(), F.length);
-const AddressRange Et(Ft.end(), E.length);
-const AddressRange injected(Et.end(), 5);
-const AddressRange H1t(injected.end(), 4); // H is split.
-const AddressRange G1t(H1t.end(), G.length); // G is copied.
-const AddressRange G2t(G1t.end(), G.length); // G is copied.
-const AddressRange H2t(G2t.end(), 3); // H is split.
-
-class BuildImageMapTest : public testing::Test {
- public:
- static const DWORD kInvalidAddress = 0xFFFFFFFF;
-
- void InitOmapData() {
- omap_data.length_original = H.end();
-
- // Build the OMAPTO vector (from transformed to original).
- omap_data.omap_to.push_back(CreateOmap(Bt.rva, B.rva));
- omap_data.omap_to.push_back(CreateOmap(Dt.rva, D.rva));
- omap_data.omap_to.push_back(CreateOmap(Ft.rva, F.rva));
- omap_data.omap_to.push_back(CreateOmap(Et.rva, E.rva));
- omap_data.omap_to.push_back(CreateOmap(injected.rva, kInvalidAddress));
- omap_data.omap_to.push_back(CreateOmap(H1t.rva, H.rva));
- omap_data.omap_to.push_back(CreateOmap(G1t.rva, G.rva));
- omap_data.omap_to.push_back(CreateOmap(G2t.rva, G.rva));
- omap_data.omap_to.push_back(CreateOmap(H2t.rva, H.rva + H1t.length));
- omap_data.omap_to.push_back(CreateOmap(H2t.end(), kInvalidAddress));
-
- // Build the OMAPFROM vector (from original to transformed).
- omap_data.omap_from.push_back(CreateOmap(B.rva, Bt.rva));
- omap_data.omap_from.push_back(CreateOmap(C.rva, kInvalidAddress));
- omap_data.omap_from.push_back(CreateOmap(D.rva, Dt.rva));
- omap_data.omap_from.push_back(CreateOmap(E.rva, Et.rva));
- omap_data.omap_from.push_back(CreateOmap(F.rva, Ft.rva));
- omap_data.omap_from.push_back(CreateOmap(G.rva, G1t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.rva, H1t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.rva + H1t.length, H2t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.end(), kInvalidAddress));
- }
-
- OmapData omap_data;
-};
-
-} // namespace
-
-TEST_F(BuildImageMapTest, EmptyImageMapOnEmptyOmapData) {
- ASSERT_EQ(0u, omap_data.omap_from.size());
- ASSERT_EQ(0u, omap_data.omap_to.size());
- ASSERT_EQ(0u, omap_data.length_original);
-
- ImageMap image_map;
- BuildImageMap(omap_data, &image_map);
- EXPECT_EQ(0u, image_map.mapping.size());
- EXPECT_EQ(0u, image_map.endpoint_index_map.size());
-}
-
-TEST_F(BuildImageMapTest, ImageMapIsCorrect) {
- InitOmapData();
- ASSERT_LE(0u, omap_data.omap_from.size());
- ASSERT_LE(0u, omap_data.omap_to.size());
- ASSERT_LE(0u, omap_data.length_original);
-
- ImageMap image_map;
- BuildImageMap(omap_data, &image_map);
- EXPECT_LE(9u, image_map.mapping.size());
- EXPECT_LE(9u, image_map.endpoint_index_map.size());
-
- Mapping mapping;
- mapping.push_back(CreateMappedRange(0, 0, B.rva, 0, 0));
- // C is removed, and it originally comes immediately after B.
- mapping.push_back(CreateMappedRange(B.rva, Bt.rva, B.length, 0, C.length));
- // D is shortened by a length of 5.
- mapping.push_back(CreateMappedRange(D.rva, Dt.rva, Dt.length, 0, 5));
- // The injected content comes immediately after E in the transformed image.
- mapping.push_back(CreateMappedRange(E.rva, Et.rva, E.length, injected.length,
- 0));
- mapping.push_back(CreateMappedRange(F.rva, Ft.rva, F.length, 0, 0));
- // G is copied so creates two entries.
- mapping.push_back(CreateMappedRange(G.rva, G1t.rva, G.length, 0, 0));
- mapping.push_back(CreateMappedRange(G.rva, G2t.rva, G.length, 0, 0));
- // H is split, so create two entries.
- mapping.push_back(CreateMappedRange(H.rva, H1t.rva, H1t.length, 0, 0));
- mapping.push_back(CreateMappedRange(H.rva + H1t.length, H2t.rva, H2t.length,
- 0, 0));
- EXPECT_THAT(mapping,
- testing::ContainerEq(image_map.mapping));
-
- EndpointIndexMap endpoint_index_map;
- endpoint_index_map.push_back(CreateEndpointIndex(0, 0));
- endpoint_index_map.push_back(CreateEndpointIndex(B.rva, 1));
- endpoint_index_map.push_back(CreateEndpointIndex(D.rva, 2));
- endpoint_index_map.push_back(CreateEndpointIndex(E.rva, 3));
- endpoint_index_map.push_back(CreateEndpointIndex(F.rva, 4));
- // G is duplicated so 2 ranges map back to it, hence the skip from 5 to 7.
- endpoint_index_map.push_back(CreateEndpointIndex(G.rva, 5));
- // H is split so we expect 2 endpoints to show up attributed to it.
- endpoint_index_map.push_back(CreateEndpointIndex(H.rva, 7));
- endpoint_index_map.push_back(CreateEndpointIndex(H.rva + H1t.length, 8));
- endpoint_index_map.push_back(CreateEndpointIndex(H.end(), 9));
- EXPECT_THAT(endpoint_index_map,
- testing::ContainerEq(image_map.endpoint_index_map));
-}
-
-namespace {
-
-class MapAddressRangeTest : public BuildImageMapTest {
- public:
- typedef BuildImageMapTest Super;
- virtual void SetUp() {
- Super::SetUp();
- InitOmapData();
- BuildImageMap(omap_data, &image_map);
- }
-
- ImageMap image_map;
-
- private:
- using BuildImageMapTest::InitOmapData;
- using BuildImageMapTest::omap_data;
-};
-
-} // namespace
-
-TEST_F(MapAddressRangeTest, EmptyImageMapReturnsIdentity) {
- ImageMap im;
- AddressRangeVector mapped_ranges;
- AddressRange ar(0, 1024);
- MapAddressRange(im, ar, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_EQ(ar, mapped_ranges[0]);
-}
-
-TEST_F(MapAddressRangeTest, MapOutOfImage) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(H.end() + 10, 10), &mapped_ranges);
- EXPECT_EQ(0u, mapped_ranges.size());
-}
-
-TEST_F(MapAddressRangeTest, MapIdentity) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, B, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(B));
-}
-
-TEST_F(MapAddressRangeTest, MapReorderedContiguous) {
- AddressRangeVector mapped_ranges;
-
- AddressRange DEF(D.rva, F.end() - D.rva);
- MapAddressRange(image_map, DEF, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange DFEt(Dt.rva, Et.end() - Dt.rva);
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(DFEt));
-}
-
-TEST_F(MapAddressRangeTest, MapEmptySingle) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(D.rva, 0), &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(Dt.rva, 0)));
-}
-
-TEST_F(MapAddressRangeTest, MapEmptyCopied) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(G.rva, 0), &mapped_ranges);
- EXPECT_EQ(2u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(G1t.rva, 0),
- AddressRange(G2t.rva, 0)));
-}
-
-TEST_F(MapAddressRangeTest, MapCopiedContiguous) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, G, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(
- AddressRange(G1t.rva, G2t.end() - G1t.rva)));
-}
-
-TEST_F(MapAddressRangeTest, MapSplitDiscontiguous) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, H, &mapped_ranges);
- EXPECT_EQ(2u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(H1t, H2t));
-}
-
-TEST_F(MapAddressRangeTest, MapInjected) {
- AddressRangeVector mapped_ranges;
-
- AddressRange EFGH(E.rva, H.end() - E.rva);
- MapAddressRange(image_map, EFGH, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange FEHGGHt(Ft.rva, H2t.end() - Ft.rva);
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(FEHGGHt));
-}
-
-TEST_F(MapAddressRangeTest, MapRemovedEntirely) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, C, &mapped_ranges);
- EXPECT_EQ(0u, mapped_ranges.size());
-}
-
-TEST_F(MapAddressRangeTest, MapRemovedPartly) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, D, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(Dt));
-}
-
-TEST_F(MapAddressRangeTest, MapFull) {
- AddressRangeVector mapped_ranges;
-
- AddressRange AH(0, H.end());
- MapAddressRange(image_map, AH, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange AHt(0, H2t.end());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AHt));
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
deleted file mode 100644
index 01f4ce3b7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
+++ /dev/null
@@ -1,1369 +0,0 @@
-// 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.
-
-#include "common/windows/pdb_source_line_writer.h"
-
-#include <windows.h>
-#include <winnt.h>
-#include <atlbase.h>
-#include <dia2.h>
-#include <diacreate.h>
-#include <ImageHlp.h>
-#include <stdio.h>
-
-#include <limits>
-#include <set>
-
-#include "common/windows/dia_util.h"
-#include "common/windows/guid_string.h"
-#include "common/windows/string_utils-inl.h"
-
-// This constant may be missing from DbgHelp.h. See the documentation for
-// IDiaSymbol::get_undecoratedNameEx.
-#ifndef UNDNAME_NO_ECSU
-#define UNDNAME_NO_ECSU 0x8000 // Suppresses enum/class/struct/union.
-#endif // UNDNAME_NO_ECSU
-
-/*
- * Not defined in WinNT.h for some reason. Definitions taken from:
- * http://uninformed.org/index.cgi?v=4&a=1&p=13
- *
- */
-typedef unsigned char UBYTE;
-
-#if !defined(_WIN64)
-#define UNW_FLAG_EHANDLER 0x01
-#define UNW_FLAG_UHANDLER 0x02
-#define UNW_FLAG_CHAININFO 0x04
-#endif
-
-union UnwindCode {
- struct {
- UBYTE offset_in_prolog;
- UBYTE unwind_operation_code : 4;
- UBYTE operation_info : 4;
- };
- USHORT frame_offset;
-};
-
-enum UnwindOperationCodes {
- UWOP_PUSH_NONVOL = 0, /* info == register number */
- UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
- UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
- UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
- UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
- UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
- // XXX: these are missing from MSDN!
- // See: http://www.osronline.com/ddkx/kmarch/64bitamd_4rs7.htm
- UWOP_SAVE_XMM,
- UWOP_SAVE_XMM_FAR,
- UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
- UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
- UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
-};
-
-// See: http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
-// Note: some fields removed as we don't use them.
-struct UnwindInfo {
- UBYTE version : 3;
- UBYTE flags : 5;
- UBYTE size_of_prolog;
- UBYTE count_of_codes;
- UBYTE frame_register : 4;
- UBYTE frame_offset : 4;
- UnwindCode unwind_code[1];
-};
-
-namespace google_breakpad {
-
-namespace {
-
-using std::vector;
-
-// A helper class to scope a PLOADED_IMAGE.
-class AutoImage {
- public:
- explicit AutoImage(PLOADED_IMAGE img) : img_(img) {}
- ~AutoImage() {
- if (img_)
- ImageUnload(img_);
- }
-
- operator PLOADED_IMAGE() { return img_; }
- PLOADED_IMAGE operator->() { return img_; }
-
- private:
- PLOADED_IMAGE img_;
-};
-
-bool CreateDiaDataSourceInstance(CComPtr<IDiaDataSource> &data_source) {
- if (SUCCEEDED(data_source.CoCreateInstance(CLSID_DiaSource))) {
- return true;
- }
-
- class DECLSPEC_UUID("B86AE24D-BF2F-4ac9-B5A2-34B14E4CE11D") DiaSource100;
- class DECLSPEC_UUID("761D3BCD-1304-41D5-94E8-EAC54E4AC172") DiaSource110;
- class DECLSPEC_UUID("3BFCEA48-620F-4B6B-81F7-B9AF75454C7D") DiaSource120;
- class DECLSPEC_UUID("E6756135-1E65-4D17-8576-610761398C3C") DiaSource140;
-
- // If the CoCreateInstance call above failed, msdia*.dll is not registered.
- // We can try loading the DLL corresponding to the #included DIA SDK, but
- // the DIA headers don't provide a version. Lets try to figure out which DIA
- // version we're compiling against by comparing CLSIDs.
- const wchar_t *msdia_dll = nullptr;
- if (CLSID_DiaSource == _uuidof(DiaSource100)) {
- msdia_dll = L"msdia100.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource110)) {
- msdia_dll = L"msdia110.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource120)) {
- msdia_dll = L"msdia120.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource140)) {
- msdia_dll = L"msdia140.dll";
- }
-
- if (msdia_dll &&
- SUCCEEDED(NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
- reinterpret_cast<void **>(&data_source)))) {
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
-PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) {
-}
-
-PDBSourceLineWriter::~PDBSourceLineWriter() {
-}
-
-bool PDBSourceLineWriter::SetCodeFile(const wstring &exe_file) {
- if (code_file_.empty()) {
- code_file_ = exe_file;
- return true;
- }
- // Setting a different code file path is an error. It is success only if the
- // file paths are the same.
- return exe_file == code_file_;
-}
-
-bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) {
- Close();
- code_file_.clear();
-
- if (FAILED(CoInitialize(NULL))) {
- fprintf(stderr, "CoInitialize failed\n");
- return false;
- }
-
- CComPtr<IDiaDataSource> data_source;
- if (!CreateDiaDataSourceInstance(data_source)) {
- const int kGuidSize = 64;
- wchar_t classid[kGuidSize] = {0};
- StringFromGUID2(CLSID_DiaSource, classid, kGuidSize);
- fprintf(stderr, "CoCreateInstance CLSID_DiaSource %S failed "
- "(msdia*.dll unregistered?)\n", classid);
- return false;
- }
-
- switch (format) {
- case PDB_FILE:
- if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
- fprintf(stderr, "loadDataFromPdb failed for %ws\n", file.c_str());
- return false;
- }
- break;
- case EXE_FILE:
- if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
- fprintf(stderr, "loadDataForExe failed for %ws\n", file.c_str());
- return false;
- }
- code_file_ = file;
- break;
- case ANY_FILE:
- if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
- if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
- fprintf(stderr, "loadDataForPdb and loadDataFromExe failed for %ws\n",
- file.c_str());
- return false;
- }
- code_file_ = file;
- }
- break;
- default:
- fprintf(stderr, "Unknown file format\n");
- return false;
- }
-
- if (FAILED(data_source->openSession(&session_))) {
- fprintf(stderr, "openSession failed\n");
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) {
- // The line number format is:
- // <rva> <line number> <source file id>
- CComPtr<IDiaLineNumber> line;
- ULONG count;
-
- while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) {
- DWORD rva;
- if (FAILED(line->get_relativeVirtualAddress(&rva))) {
- fprintf(stderr, "failed to get line rva\n");
- return false;
- }
-
- DWORD length;
- if (FAILED(line->get_length(&length))) {
- fprintf(stderr, "failed to get line code length\n");
- return false;
- }
-
- DWORD dia_source_id;
- if (FAILED(line->get_sourceFileId(&dia_source_id))) {
- fprintf(stderr, "failed to get line source file id\n");
- return false;
- }
- // duplicate file names are coalesced to share one ID
- DWORD source_id = GetRealFileID(dia_source_id);
-
- DWORD line_num;
- if (FAILED(line->get_lineNumber(&line_num))) {
- fprintf(stderr, "failed to get line number\n");
- return false;
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, length), &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "%x %x %d %d\n", ranges[i].rva, ranges[i].length,
- line_num, source_id);
- }
- line.Release();
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
- IDiaSymbol *block) {
- // The function format is:
- // FUNC <address> <length> <param_stack_size> <function>
- DWORD rva;
- if (FAILED(block->get_relativeVirtualAddress(&rva))) {
- fprintf(stderr, "couldn't get rva\n");
- return false;
- }
-
- ULONGLONG length;
- if (FAILED(block->get_length(&length))) {
- fprintf(stderr, "failed to get function length\n");
- return false;
- }
-
- if (length == 0) {
- // Silently ignore zero-length functions, which can infrequently pop up.
- return true;
- }
-
- CComBSTR name;
- int stack_param_size;
- if (!GetSymbolFunctionName(function, &name, &stack_param_size)) {
- return false;
- }
-
- // If the decorated name didn't give the parameter size, try to
- // calculate it.
- if (stack_param_size < 0) {
- stack_param_size = GetFunctionStackParamSize(function);
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, static_cast<DWORD>(length)),
- &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "FUNC %x %x %x %ws\n",
- ranges[i].rva, ranges[i].length, stack_param_size,
- name.m_str);
- }
-
- CComPtr<IDiaEnumLineNumbers> lines;
- if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) {
- return false;
- }
-
- if (!PrintLines(lines)) {
- return false;
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintSourceFiles() {
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumSymbols> compilands;
- if (FAILED(global->findChildren(SymTagCompiland, NULL,
- nsNone, &compilands))) {
- fprintf(stderr, "findChildren failed\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> compiland;
- ULONG count;
- while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
- CComPtr<IDiaEnumSourceFiles> source_files;
- if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) {
- return false;
- }
- CComPtr<IDiaSourceFile> file;
- while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) {
- DWORD file_id;
- if (FAILED(file->get_uniqueId(&file_id))) {
- return false;
- }
-
- CComBSTR file_name;
- if (FAILED(file->get_fileName(&file_name))) {
- return false;
- }
-
- wstring file_name_string(file_name);
- if (!FileIDIsCached(file_name_string)) {
- // this is a new file name, cache it and output a FILE line.
- CacheFileID(file_name_string, file_id);
- fwprintf(output_, L"FILE %d %ws\n", file_id, file_name_string.c_str());
- } else {
- // this file name has already been seen, just save this
- // ID for later lookup.
- StoreDuplicateFileID(file_name_string, file_id);
- }
- file.Release();
- }
- compiland.Release();
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFunctions() {
- ULONG count = 0;
- DWORD rva = 0;
- CComPtr<IDiaSymbol> global;
- HRESULT hr;
-
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumSymbols> symbols = NULL;
-
- // Find all function symbols first.
- std::set<DWORD> rvas;
- hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols);
-
- if (SUCCEEDED(hr)) {
- CComPtr<IDiaSymbol> symbol = NULL;
-
- while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
- if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
- // To maintain existing behavior of one symbol per address, place the
- // rva onto a set here to uniquify them.
- rvas.insert(rva);
- } else {
- fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
- return false;
- }
-
- symbol.Release();
- }
-
- symbols.Release();
- }
-
- // Find all public symbols. Store public symbols that are not also private
- // symbols for later.
- std::set<DWORD> public_only_rvas;
- hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols);
-
- if (SUCCEEDED(hr)) {
- CComPtr<IDiaSymbol> symbol = NULL;
-
- while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
- if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
- if (rvas.count(rva) == 0) {
- rvas.insert(rva); // Keep symbols in rva order.
- public_only_rvas.insert(rva);
- }
- } else {
- fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
- return false;
- }
-
- symbol.Release();
- }
-
- symbols.Release();
- }
-
- std::set<DWORD>::iterator it;
-
- // For each rva, dump the first symbol DIA knows about at the address.
- for (it = rvas.begin(); it != rvas.end(); ++it) {
- CComPtr<IDiaSymbol> symbol = NULL;
- // If the symbol is not in the public list, look for SymTagFunction. This is
- // a workaround to a bug where DIA will hang if searching for a private
- // symbol at an address where only a public symbol exists.
- // See http://connect.microsoft.com/VisualStudio/feedback/details/722366
- if (public_only_rvas.count(*it) == 0) {
- if (SUCCEEDED(session_->findSymbolByRVA(*it, SymTagFunction, &symbol))) {
- // Sometimes findSymbolByRVA returns S_OK, but NULL.
- if (symbol) {
- if (!PrintFunction(symbol, symbol))
- return false;
- symbol.Release();
- }
- } else {
- fprintf(stderr, "findSymbolByRVA SymTagFunction failed\n");
- return false;
- }
- } else if (SUCCEEDED(session_->findSymbolByRVA(*it,
- SymTagPublicSymbol,
- &symbol))) {
- // Sometimes findSymbolByRVA returns S_OK, but NULL.
- if (symbol) {
- if (!PrintCodePublicSymbol(symbol))
- return false;
- symbol.Release();
- }
- } else {
- fprintf(stderr, "findSymbolByRVA SymTagPublicSymbol failed\n");
- return false;
- }
- }
-
- // When building with PGO, the compiler can split functions into
- // "hot" and "cold" blocks, and move the "cold" blocks out to separate
- // pages, so the function can be noncontiguous. To find these blocks,
- // we have to iterate over all the compilands, and then find blocks
- // that are children of them. We can then find the lexical parents
- // of those blocks and print out an extra FUNC line for blocks
- // that are not contained in their parent functions.
- CComPtr<IDiaEnumSymbols> compilands;
- if (FAILED(global->findChildren(SymTagCompiland, NULL,
- nsNone, &compilands))) {
- fprintf(stderr, "findChildren failed on the global\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> compiland;
- while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
- CComPtr<IDiaEnumSymbols> blocks;
- if (FAILED(compiland->findChildren(SymTagBlock, NULL,
- nsNone, &blocks))) {
- fprintf(stderr, "findChildren failed on a compiland\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> block;
- while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) {
- // find this block's lexical parent function
- CComPtr<IDiaSymbol> parent;
- DWORD tag;
- if (SUCCEEDED(block->get_lexicalParent(&parent)) &&
- SUCCEEDED(parent->get_symTag(&tag)) &&
- tag == SymTagFunction) {
- // now get the block's offset and the function's offset and size,
- // and determine if the block is outside of the function
- DWORD func_rva, block_rva;
- ULONGLONG func_length;
- if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) &&
- SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) &&
- SUCCEEDED(parent->get_length(&func_length))) {
- if (block_rva < func_rva || block_rva > (func_rva + func_length)) {
- if (!PrintFunction(parent, block)) {
- return false;
- }
- }
- }
- }
- parent.Release();
- block.Release();
- }
- blocks.Release();
- compiland.Release();
- }
-
- global.Release();
- return true;
-}
-
-#undef max
-
-bool PDBSourceLineWriter::PrintFrameDataUsingPDB() {
- // It would be nice if it were possible to output frame data alongside the
- // associated function, as is done with line numbers, but the DIA API
- // doesn't make it possible to get the frame data in that way.
-
- CComPtr<IDiaEnumFrameData> frame_data_enum;
- if (!FindTable(session_, &frame_data_enum))
- return false;
-
- DWORD last_type = std::numeric_limits<DWORD>::max();
- DWORD last_rva = std::numeric_limits<DWORD>::max();
- DWORD last_code_size = 0;
- DWORD last_prolog_size = std::numeric_limits<DWORD>::max();
-
- CComPtr<IDiaFrameData> frame_data;
- ULONG count = 0;
- while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) &&
- count == 1) {
- DWORD type;
- if (FAILED(frame_data->get_type(&type)))
- return false;
-
- DWORD rva;
- if (FAILED(frame_data->get_relativeVirtualAddress(&rva)))
- return false;
-
- DWORD code_size;
- if (FAILED(frame_data->get_lengthBlock(&code_size)))
- return false;
-
- DWORD prolog_size;
- if (FAILED(frame_data->get_lengthProlog(&prolog_size)))
- return false;
-
- // parameter_size is the size of parameters passed on the stack. If any
- // parameters are not passed on the stack (such as in registers), their
- // sizes will not be included in parameter_size.
- DWORD parameter_size;
- if (FAILED(frame_data->get_lengthParams(&parameter_size)))
- return false;
-
- DWORD saved_register_size;
- if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size)))
- return false;
-
- DWORD local_size;
- if (FAILED(frame_data->get_lengthLocals(&local_size)))
- return false;
-
- // get_maxStack can return S_FALSE, just use 0 in that case.
- DWORD max_stack_size = 0;
- if (FAILED(frame_data->get_maxStack(&max_stack_size)))
- return false;
-
- // get_programString can return S_FALSE, indicating that there is no
- // program string. In that case, check whether %ebp is used.
- HRESULT program_string_result;
- CComBSTR program_string;
- if (FAILED(program_string_result = frame_data->get_program(
- &program_string))) {
- return false;
- }
-
- // get_allocatesBasePointer can return S_FALSE, treat that as though
- // %ebp is not used.
- BOOL allocates_base_pointer = FALSE;
- if (program_string_result != S_OK) {
- if (FAILED(frame_data->get_allocatesBasePointer(
- &allocates_base_pointer))) {
- return false;
- }
- }
-
- // Only print out a line if type, rva, code_size, or prolog_size have
- // changed from the last line. It is surprisingly common (especially in
- // system library PDBs) for DIA to return a series of identical
- // IDiaFrameData objects. For kernel32.pdb from Windows XP SP2 on x86,
- // this check reduces the size of the dumped symbol file by a third.
- if (type != last_type || rva != last_rva || code_size != last_code_size ||
- prolog_size != last_prolog_size) {
- // The prolog and the code portions of the frame have to be treated
- // independently as they may have independently changed in size, or may
- // even have been split.
- // NOTE: If epilog size is ever non-zero, we have to do something
- // similar with it.
-
- // Figure out where the prolog bytes have landed.
- AddressRangeVector prolog_ranges;
- if (prolog_size > 0) {
- MapAddressRange(image_map_, AddressRange(rva, prolog_size),
- &prolog_ranges);
- }
-
- // And figure out where the code bytes have landed.
- AddressRangeVector code_ranges;
- MapAddressRange(image_map_,
- AddressRange(rva + prolog_size,
- code_size - prolog_size),
- &code_ranges);
-
- struct FrameInfo {
- DWORD rva;
- DWORD code_size;
- DWORD prolog_size;
- };
- std::vector<FrameInfo> frame_infos;
-
- // Special case: The prolog and the code bytes remain contiguous. This is
- // only done for compactness of the symbol file, and we could actually
- // be outputting independent frame info for the prolog and code portions.
- if (prolog_ranges.size() == 1 && code_ranges.size() == 1 &&
- prolog_ranges[0].end() == code_ranges[0].rva) {
- FrameInfo fi = { prolog_ranges[0].rva,
- prolog_ranges[0].length + code_ranges[0].length,
- prolog_ranges[0].length };
- frame_infos.push_back(fi);
- } else {
- // Otherwise we output the prolog and code frame info independently.
- for (size_t i = 0; i < prolog_ranges.size(); ++i) {
- FrameInfo fi = { prolog_ranges[i].rva,
- prolog_ranges[i].length,
- prolog_ranges[i].length };
- frame_infos.push_back(fi);
- }
- for (size_t i = 0; i < code_ranges.size(); ++i) {
- FrameInfo fi = { code_ranges[i].rva, code_ranges[i].length, 0 };
- frame_infos.push_back(fi);
- }
- }
-
- for (size_t i = 0; i < frame_infos.size(); ++i) {
- const FrameInfo& fi(frame_infos[i]);
- fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ",
- type, fi.rva, fi.code_size, fi.prolog_size,
- 0 /* epilog_size */, parameter_size, saved_register_size,
- local_size, max_stack_size, program_string_result == S_OK);
- if (program_string_result == S_OK) {
- fprintf(output_, "%ws\n", program_string.m_str);
- } else {
- fprintf(output_, "%d\n", allocates_base_pointer);
- }
- }
-
- last_type = type;
- last_rva = rva;
- last_code_size = code_size;
- last_prolog_size = prolog_size;
- }
-
- frame_data.Release();
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
- if (code_file_.empty() && !FindPEFile()) {
- fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
- return false;
- }
-
- // Convert wchar to native charset because ImageLoad only takes
- // a PSTR as input.
- string code_file;
- if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
- return false;
- }
-
- AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
- if (!img) {
- fprintf(stderr, "Failed to load %s\n", code_file.c_str());
- return false;
- }
- PIMAGE_OPTIONAL_HEADER64 optional_header =
- &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
- if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- fprintf(stderr, "Not a PE32+ image\n");
- return false;
- }
-
- // Read Exception Directory
- DWORD exception_rva = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
- DWORD exception_size = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
- PIMAGE_RUNTIME_FUNCTION_ENTRY funcs =
- static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- exception_rva,
- &img->LastRvaSection));
- for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
- DWORD unwind_rva = funcs[i].UnwindInfoAddress;
- // handle chaining
- while (unwind_rva & 0x1) {
- unwind_rva ^= 0x1;
- PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
- static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
- unwind_rva = chained_func->UnwindInfoAddress;
- }
-
- UnwindInfo *unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
-
- DWORD stack_size = 8; // minimal stack size is 8 for RIP
- DWORD rip_offset = 8;
- do {
- for (UBYTE c = 0; c < unwind_info->count_of_codes; c++) {
- UnwindCode *unwind_code = &unwind_info->unwind_code[c];
- switch (unwind_code->unwind_operation_code) {
- case UWOP_PUSH_NONVOL: {
- stack_size += 8;
- break;
- }
- case UWOP_ALLOC_LARGE: {
- if (unwind_code->operation_info == 0) {
- c++;
- if (c < unwind_info->count_of_codes)
- stack_size += (unwind_code + 1)->frame_offset * 8;
- } else {
- c += 2;
- if (c < unwind_info->count_of_codes)
- stack_size += (unwind_code + 1)->frame_offset |
- ((unwind_code + 2)->frame_offset << 16);
- }
- break;
- }
- case UWOP_ALLOC_SMALL: {
- stack_size += unwind_code->operation_info * 8 + 8;
- break;
- }
- case UWOP_SET_FPREG:
- case UWOP_SAVE_XMM:
- case UWOP_SAVE_XMM_FAR:
- break;
- case UWOP_SAVE_NONVOL:
- case UWOP_SAVE_XMM128: {
- c++; // skip slot with offset
- break;
- }
- case UWOP_SAVE_NONVOL_FAR:
- case UWOP_SAVE_XMM128_FAR: {
- c += 2; // skip 2 slots with offset
- break;
- }
- case UWOP_PUSH_MACHFRAME: {
- if (unwind_code->operation_info) {
- stack_size += 88;
- } else {
- stack_size += 80;
- }
- rip_offset += 80;
- break;
- }
- }
- }
- if (unwind_info->flags & UNW_FLAG_CHAININFO) {
- PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
- reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- (unwind_info->unwind_code +
- ((unwind_info->count_of_codes + 1) & ~1)));
-
- unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- chained_func->UnwindInfoAddress,
- &img->LastRvaSection));
- } else {
- unwind_info = NULL;
- }
- } while (unwind_info);
- fprintf(output_, "STACK CFI INIT %x %x .cfa: $rsp .ra: .cfa %d - ^\n",
- funcs[i].BeginAddress,
- funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
- fprintf(output_, "STACK CFI %x .cfa: $rsp %d +\n",
- funcs[i].BeginAddress, stack_size);
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFrameData() {
- PDBModuleInfo info;
- if (GetModuleInfo(&info) && info.cpu == L"x86_64") {
- return PrintFrameDataUsingEXE();
- } else {
- return PrintFrameDataUsingPDB();
- }
- return false;
-}
-
-bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) {
- BOOL is_code;
- if (FAILED(symbol->get_code(&is_code))) {
- return false;
- }
- if (!is_code) {
- return true;
- }
-
- DWORD rva;
- if (FAILED(symbol->get_relativeVirtualAddress(&rva))) {
- return false;
- }
-
- CComBSTR name;
- int stack_param_size;
- if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) {
- return false;
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, 1), &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "PUBLIC %x %x %ws\n", ranges[i].rva,
- stack_param_size > 0 ? stack_param_size : 0,
- name.m_str);
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintPDBInfo() {
- PDBModuleInfo info;
- if (!GetModuleInfo(&info)) {
- return false;
- }
-
- // Hard-code "windows" for the OS because that's the only thing that makes
- // sense for PDB files. (This might not be strictly correct for Windows CE
- // support, but we don't care about that at the moment.)
- fprintf(output_, "MODULE windows %ws %ws %ws\n",
- info.cpu.c_str(), info.debug_identifier.c_str(),
- info.debug_file.c_str());
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintPEInfo() {
- PEModuleInfo info;
- if (!GetPEInfo(&info)) {
- return false;
- }
-
- fprintf(output_, "INFO CODE_ID %ws %ws\n",
- info.code_identifier.c_str(),
- info.code_file.c_str());
- return true;
-}
-
-// wcstol_positive_strict is sort of like wcstol, but much stricter. string
-// should be a buffer pointing to a null-terminated string containing only
-// decimal digits. If the entire string can be converted to an integer
-// without overflowing, and there are no non-digit characters before the
-// result is set to the value and this function returns true. Otherwise,
-// this function returns false. This is an alternative to the strtol, atoi,
-// and scanf families, which are not as strict about input and in some cases
-// don't provide a good way for the caller to determine if a conversion was
-// successful.
-static bool wcstol_positive_strict(wchar_t *string, int *result) {
- int value = 0;
- for (wchar_t *c = string; *c != '\0'; ++c) {
- int last_value = value;
- value *= 10;
- // Detect overflow.
- if (value / 10 != last_value || value < 0) {
- return false;
- }
- if (*c < '0' || *c > '9') {
- return false;
- }
- unsigned int c_value = *c - '0';
- last_value = value;
- value += c_value;
- // Detect overflow.
- if (value < last_value) {
- return false;
- }
- // Forbid leading zeroes unless the string is just "0".
- if (value == 0 && *(c+1) != '\0') {
- return false;
- }
- }
- *result = value;
- return true;
-}
-
-bool PDBSourceLineWriter::FindPEFile() {
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComBSTR symbols_file;
- if (SUCCEEDED(global->get_symbolsFileName(&symbols_file))) {
- wstring file(symbols_file);
-
- // Look for an EXE or DLL file.
- const wchar_t *extensions[] = { L"exe", L"dll" };
- for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) {
- size_t dot_pos = file.find_last_of(L".");
- if (dot_pos != wstring::npos) {
- file.replace(dot_pos + 1, wstring::npos, extensions[i]);
- // Check if this file exists.
- if (GetFileAttributesW(file.c_str()) != INVALID_FILE_ATTRIBUTES) {
- code_file_ = file;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-// static
-bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function,
- BSTR *name,
- int *stack_param_size) {
- *stack_param_size = -1;
- const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS |
- UNDNAME_NO_FUNCTION_RETURNS |
- UNDNAME_NO_ALLOCATION_MODEL |
- UNDNAME_NO_ALLOCATION_LANGUAGE |
- UNDNAME_NO_THISTYPE |
- UNDNAME_NO_ACCESS_SPECIFIERS |
- UNDNAME_NO_THROW_SIGNATURES |
- UNDNAME_NO_MEMBER_TYPE |
- UNDNAME_NO_RETURN_UDT_MODEL |
- UNDNAME_NO_ECSU;
-
- // Use get_undecoratedNameEx to get readable C++ names with arguments.
- if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) {
- if (function->get_name(name) != S_OK) {
- fprintf(stderr, "failed to get function name\n");
- return false;
- }
-
- // It's possible for get_name to return an empty string, so
- // special-case that.
- if (wcscmp(*name, L"") == 0) {
- SysFreeString(*name);
- // dwarf_cu_to_module.cc uses "<name omitted>", so match that.
- *name = SysAllocString(L"<name omitted>");
- return true;
- }
-
- // If a name comes from get_name because no undecorated form existed,
- // it's already formatted properly to be used as output. Don't do any
- // additional processing.
- //
- // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's.
- // This will result in calling get_name for some C++ symbols, so
- // all of the parameter and return type information may not be included in
- // the name string.
- } else {
- // C++ uses a bogus "void" argument for functions and methods that don't
- // take any parameters. Take it out of the undecorated name because it's
- // ugly and unnecessary.
- const wchar_t *replace_string = L"(void)";
- const size_t replace_length = wcslen(replace_string);
- const wchar_t *replacement_string = L"()";
- size_t length = wcslen(*name);
- if (length >= replace_length) {
- wchar_t *name_end = *name + length - replace_length;
- if (wcscmp(name_end, replace_string) == 0) {
- WindowsStringUtils::safe_wcscpy(name_end, replace_length,
- replacement_string);
- length = wcslen(*name);
- }
- }
-
- // Undecorate names used for stdcall and fastcall. These names prefix
- // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it
- // with '@' followed by the number of bytes of parameters, in decimal.
- // If such a name is found, take note of the size and undecorate it.
- // Only do this for names that aren't C++, which is determined based on
- // whether the undecorated name contains any ':' or '(' characters.
- if (!wcschr(*name, ':') && !wcschr(*name, '(') &&
- (*name[0] == '_' || *name[0] == '@')) {
- wchar_t *last_at = wcsrchr(*name + 1, '@');
- if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) {
- // If this function adheres to the fastcall convention, it accepts up
- // to the first 8 bytes of parameters in registers (%ecx and %edx).
- // We're only interested in the stack space used for parameters, so
- // so subtract 8 and don't let the size go below 0.
- if (*name[0] == '@') {
- if (*stack_param_size > 8) {
- *stack_param_size -= 8;
- } else {
- *stack_param_size = 0;
- }
- }
-
- // Undecorate the name by moving it one character to the left in its
- // buffer, and terminating it where the last '@' had been.
- WindowsStringUtils::safe_wcsncpy(*name, length,
- *name + 1, last_at - *name - 1);
- } else if (*name[0] == '_') {
- // This symbol's name is encoded according to the cdecl rules. The
- // name doesn't end in a '@' character followed by a decimal positive
- // integer, so it's not a stdcall name. Strip off the leading
- // underscore.
- WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length);
- }
- }
- }
-
- return true;
-}
-
-// static
-int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) {
- // This implementation is highly x86-specific.
-
- // Gather the symbols corresponding to data.
- CComPtr<IDiaEnumSymbols> data_children;
- if (FAILED(function->findChildren(SymTagData, NULL, nsNone,
- &data_children))) {
- return 0;
- }
-
- // lowest_base is the lowest %ebp-relative byte offset used for a parameter.
- // highest_end is one greater than the highest offset (i.e. base + length).
- // Stack parameters are assumed to be contiguous, because in reality, they
- // are.
- int lowest_base = INT_MAX;
- int highest_end = INT_MIN;
-
- CComPtr<IDiaSymbol> child;
- DWORD count;
- while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) {
- // If any operation fails at this point, just proceed to the next child.
- // Use the next_child label instead of continue because child needs to
- // be released before it's reused. Declare constructable/destructable
- // types early to avoid gotos that cross initializations.
- CComPtr<IDiaSymbol> child_type;
-
- // DataIsObjectPtr is only used for |this|. Because |this| can be passed
- // as a stack parameter, look for it in addition to traditional
- // parameters.
- DWORD child_kind;
- if (FAILED(child->get_dataKind(&child_kind)) ||
- (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) {
- goto next_child;
- }
-
- // Only concentrate on register-relative parameters. Parameters may also
- // be enregistered (passed directly in a register), but those don't
- // consume any stack space, so they're not of interest.
- DWORD child_location_type;
- if (FAILED(child->get_locationType(&child_location_type)) ||
- child_location_type != LocIsRegRel) {
- goto next_child;
- }
-
- // Of register-relative parameters, the only ones that make any sense are
- // %ebp- or %esp-relative. Note that MSVC's debugging information always
- // gives parameters as %ebp-relative even when a function doesn't use a
- // traditional frame pointer and stack parameters are accessed relative to
- // %esp, so just look for %ebp-relative parameters. If you wanted to
- // access parameters, you'd probably want to treat these %ebp-relative
- // offsets as if they were relative to %esp before a function's prolog
- // executed.
- DWORD child_register;
- if (FAILED(child->get_registerId(&child_register)) ||
- child_register != CV_REG_EBP) {
- goto next_child;
- }
-
- LONG child_register_offset;
- if (FAILED(child->get_offset(&child_register_offset))) {
- goto next_child;
- }
-
- // IDiaSymbol::get_type can succeed but still pass back a NULL value.
- if (FAILED(child->get_type(&child_type)) || !child_type) {
- goto next_child;
- }
-
- ULONGLONG child_length;
- if (FAILED(child_type->get_length(&child_length))) {
- goto next_child;
- }
-
- int child_end = child_register_offset + static_cast<ULONG>(child_length);
- if (child_register_offset < lowest_base) {
- lowest_base = child_register_offset;
- }
- if (child_end > highest_end) {
- highest_end = child_end;
- }
-
-next_child:
- child.Release();
- }
-
- int param_size = 0;
- // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest
- // possible address to find a stack parameter before executing a function's
- // prolog (see above). Some optimizations cause parameter offsets to be
- // lower than 4, but we're not concerned with those because we're only
- // looking for parameters contained in addresses higher than where the
- // return address is stored.
- if (lowest_base < 4) {
- lowest_base = 4;
- }
- if (highest_end > lowest_base) {
- // All stack parameters are pushed as at least 4-byte quantities. If the
- // last type was narrower than 4 bytes, promote it. This assumes that all
- // parameters' offsets are 4-byte-aligned, which is always the case. Only
- // worry about the last type, because we're not summing the type sizes,
- // just looking at the lowest and highest offsets.
- int remainder = highest_end % 4;
- if (remainder) {
- highest_end += 4 - remainder;
- }
-
- param_size = highest_end - lowest_base;
- }
-
- return param_size;
-}
-
-bool PDBSourceLineWriter::WriteMap(FILE *map_file) {
- output_ = map_file;
-
- // Load the OMAP information, and disable auto-translation of addresses in
- // preference of doing it ourselves.
- OmapData omap_data;
- if (!GetOmapDataAndDisableTranslation(session_, &omap_data))
- return false;
- BuildImageMap(omap_data, &image_map_);
-
- bool ret = PrintPDBInfo();
- // This is not a critical piece of the symbol file.
- PrintPEInfo();
- ret = ret &&
- PrintSourceFiles() &&
- PrintFunctions() &&
- PrintFrameData();
-
- output_ = NULL;
- return ret;
-}
-
-void PDBSourceLineWriter::Close() {
- session_.Release();
-}
-
-bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) {
- if (!info) {
- return false;
- }
-
- info->debug_file.clear();
- info->debug_identifier.clear();
- info->cpu.clear();
-
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- return false;
- }
-
- DWORD machine_type;
- // get_machineType can return S_FALSE.
- if (global->get_machineType(&machine_type) == S_OK) {
- // The documentation claims that get_machineType returns a value from
- // the CV_CPU_TYPE_e enumeration, but that's not the case.
- // Instead, it returns one of the IMAGE_FILE_MACHINE values as
- // defined here:
- // http://msdn.microsoft.com/en-us/library/ms680313%28VS.85%29.aspx
- switch (machine_type) {
- case IMAGE_FILE_MACHINE_I386:
- info->cpu = L"x86";
- break;
- case IMAGE_FILE_MACHINE_AMD64:
- info->cpu = L"x86_64";
- break;
- default:
- info->cpu = L"unknown";
- break;
- }
- } else {
- // Unexpected, but handle gracefully.
- info->cpu = L"unknown";
- }
-
- // DWORD* and int* are not compatible. This is clean and avoids a cast.
- DWORD age;
- if (FAILED(global->get_age(&age))) {
- return false;
- }
-
- bool uses_guid;
- if (!UsesGUID(&uses_guid)) {
- return false;
- }
-
- if (uses_guid) {
- GUID guid;
- if (FAILED(global->get_guid(&guid))) {
- return false;
- }
-
- // Use the same format that the MS symbol server uses in filesystem
- // hierarchies.
- wchar_t age_string[9];
- swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]),
- L"%x", age);
-
- // remove when VC++7.1 is no longer supported
- age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0';
-
- info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid);
- info->debug_identifier.append(age_string);
- } else {
- DWORD signature;
- if (FAILED(global->get_signature(&signature))) {
- return false;
- }
-
- // Use the same format that the MS symbol server uses in filesystem
- // hierarchies.
- wchar_t identifier_string[17];
- swprintf(identifier_string,
- sizeof(identifier_string) / sizeof(identifier_string[0]),
- L"%08X%x", signature, age);
-
- // remove when VC++7.1 is no longer supported
- identifier_string[sizeof(identifier_string) /
- sizeof(identifier_string[0]) - 1] = L'\0';
-
- info->debug_identifier = identifier_string;
- }
-
- CComBSTR debug_file_string;
- if (FAILED(global->get_symbolsFileName(&debug_file_string))) {
- return false;
- }
- info->debug_file =
- WindowsStringUtils::GetBaseName(wstring(debug_file_string));
-
- return true;
-}
-
-bool PDBSourceLineWriter::GetPEInfo(PEModuleInfo *info) {
- if (!info) {
- return false;
- }
-
- if (code_file_.empty() && !FindPEFile()) {
- fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
- return false;
- }
-
- // Convert wchar to native charset because ImageLoad only takes
- // a PSTR as input.
- string code_file;
- if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
- return false;
- }
-
- AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
- if (!img) {
- fprintf(stderr, "Failed to open PE file: %s\n", code_file.c_str());
- return false;
- }
-
- info->code_file = WindowsStringUtils::GetBaseName(code_file_);
-
- // The date and time that the file was created by the linker.
- DWORD TimeDateStamp = img->FileHeader->FileHeader.TimeDateStamp;
- // The size of the file in bytes, including all headers.
- DWORD SizeOfImage = 0;
- PIMAGE_OPTIONAL_HEADER64 opt =
- &((PIMAGE_NT_HEADERS64)img->FileHeader)->OptionalHeader;
- if (opt->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- // 64-bit PE file.
- SizeOfImage = opt->SizeOfImage;
- } else {
- // 32-bit PE file.
- SizeOfImage = img->FileHeader->OptionalHeader.SizeOfImage;
- }
- wchar_t code_identifier[32];
- swprintf(code_identifier,
- sizeof(code_identifier) / sizeof(code_identifier[0]),
- L"%08X%X", TimeDateStamp, SizeOfImage);
- info->code_identifier = code_identifier;
-
- return true;
-}
-
-bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) {
- if (!uses_guid)
- return false;
-
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global)))
- return false;
-
- GUID guid;
- if (FAILED(global->get_guid(&guid)))
- return false;
-
- DWORD signature;
- if (FAILED(global->get_signature(&signature)))
- return false;
-
- // There are two possibilities for guid: either it's a real 128-bit GUID
- // as identified in a code module by a new-style CodeView record, or it's
- // a 32-bit signature (timestamp) as identified by an old-style record.
- // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h.
- //
- // Because DIA doesn't provide a way to directly determine whether a module
- // uses a GUID or a 32-bit signature, this code checks whether the first 32
- // bits of guid are the same as the signature, and if the rest of guid is
- // zero. If so, then with a pretty high degree of certainty, there's an
- // old-style CodeView record in use. This method will only falsely find an
- // an old-style CodeView record if a real 128-bit GUID has its first 32
- // bits set the same as the module's signature (timestamp) and the rest of
- // the GUID is set to 0. This is highly unlikely.
-
- GUID signature_guid = {signature}; // 0-initializes other members
- *uses_guid = !IsEqualGUID(guid, signature_guid);
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
deleted file mode 100644
index e9e89bb27..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
+++ /dev/null
@@ -1,257 +0,0 @@
-// 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.
-
-// PDBSourceLineWriter uses a pdb file produced by Visual C++ to output
-// a line/address map for use with BasicSourceLineResolver.
-
-#ifndef COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
-#define COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
-
-#include <atlcomcli.h>
-
-#include <unordered_map>
-#include <string>
-
-#include "common/windows/omap.h"
-
-struct IDiaEnumLineNumbers;
-struct IDiaSession;
-struct IDiaSymbol;
-
-namespace google_breakpad {
-
-using std::wstring;
-using std::unordered_map;
-
-// A structure that carries information that identifies a pdb file.
-struct PDBModuleInfo {
- public:
- // The basename of the pdb file from which information was loaded.
- wstring debug_file;
-
- // The pdb's identifier. For recent pdb files, the identifier consists
- // of the pdb's guid, in uppercase hexadecimal form without any dashes
- // or separators, followed immediately by the pdb's age, also in
- // uppercase hexadecimal form. For older pdb files which have no guid,
- // the identifier is the pdb's 32-bit signature value, in zero-padded
- // hexadecimal form, followed immediately by the pdb's age, in lowercase
- // hexadecimal form.
- wstring debug_identifier;
-
- // A string identifying the cpu that the pdb is associated with.
- // Currently, this may be "x86" or "unknown".
- wstring cpu;
-};
-
-// A structure that carries information that identifies a PE file,
-// either an EXE or a DLL.
-struct PEModuleInfo {
- // The basename of the PE file.
- wstring code_file;
-
- // The PE file's code identifier, which consists of its timestamp
- // and file size concatenated together into a single hex string.
- // (The fields IMAGE_OPTIONAL_HEADER::SizeOfImage and
- // IMAGE_FILE_HEADER::TimeDateStamp, as defined in the ImageHlp
- // documentation.) This is not well documented, if it's documented
- // at all, but it's what symstore does and what DbgHelp supports.
- wstring code_identifier;
-};
-
-class PDBSourceLineWriter {
- public:
- enum FileFormat {
- PDB_FILE, // a .pdb file containing debug symbols
- EXE_FILE, // a .exe or .dll file
- ANY_FILE // try PDB_FILE and then EXE_FILE
- };
-
- explicit PDBSourceLineWriter();
- ~PDBSourceLineWriter();
-
- // Opens the given file. For executable files, the corresponding pdb
- // file must be available; Open will be if it is not.
- // If there is already a pdb file open, it is automatically closed.
- // Returns true on success.
- bool Open(const wstring &file, FileFormat format);
-
- // Sets the code file full path. This is optional for 32-bit modules. It is
- // also optional for 64-bit modules when there is an executable file stored
- // in the same directory as the PDB file. It is only required for 64-bit
- // modules when the executable file is not in the same location as the PDB
- // file and it must be called after Open() and before WriteMap().
- // If Open() was called for an executable file, then it is an error to call
- // SetCodeFile() with a different file path and it will return false.
- bool SetCodeFile(const wstring &exe_file);
-
- // Writes a map file from the current pdb file to the given file stream.
- // Returns true on success.
- bool WriteMap(FILE *map_file);
-
- // Closes the current pdb file and its associated resources.
- void Close();
-
- // Retrieves information about the module's debugging file. Returns
- // true on success and false on failure.
- bool GetModuleInfo(PDBModuleInfo *info);
-
- // Retrieves information about the module's PE file. Returns
- // true on success and false on failure.
- bool GetPEInfo(PEModuleInfo *info);
-
- // Sets uses_guid to true if the opened file uses a new-style CodeView
- // record with a 128-bit GUID, or false if the opened file uses an old-style
- // CodeView record. When no GUID is available, a 32-bit signature should be
- // used to identify the module instead. If the information cannot be
- // determined, this method returns false.
- bool UsesGUID(bool *uses_guid);
-
- private:
- // Outputs the line/address pairs for each line in the enumerator.
- // Returns true on success.
- bool PrintLines(IDiaEnumLineNumbers *lines);
-
- // Outputs a function address and name, followed by its source line list.
- // block can be the same object as function, or it can be a reference
- // to a code block that is lexically part of this function, but
- // resides at a separate address.
- // Returns true on success.
- bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block);
-
- // Outputs all functions as described above. Returns true on success.
- bool PrintFunctions();
-
- // Outputs all of the source files in the session's pdb file.
- // Returns true on success.
- bool PrintSourceFiles();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. For x86 data stored in
- // .pdb files. Returns true on success.
- bool PrintFrameDataUsingPDB();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. For x64 data stored in
- // .exe, .dll files. Returns true on success.
- bool PrintFrameDataUsingEXE();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. Returns true on success.
- bool PrintFrameData();
-
- // Outputs a single public symbol address and name, if the symbol corresponds
- // to a code address. Returns true on success. If symbol is does not
- // correspond to code, returns true without outputting anything.
- bool PrintCodePublicSymbol(IDiaSymbol *symbol);
-
- // Outputs a line identifying the PDB file that is being dumped, along with
- // its uuid and age.
- bool PrintPDBInfo();
-
- // Outputs a line identifying the PE file corresponding to the PDB
- // file that is being dumped, along with its code identifier,
- // which consists of its timestamp and file size.
- bool PrintPEInfo();
-
- // Returns true if this filename has already been seen,
- // and an ID is stored for it, or false if it has not.
- bool FileIDIsCached(const wstring &file) {
- return unique_files_.find(file) != unique_files_.end();
- }
-
- // Cache this filename and ID for later reuse.
- void CacheFileID(const wstring &file, DWORD id) {
- unique_files_[file] = id;
- }
-
- // Store this ID in the cache as a duplicate for this filename.
- void StoreDuplicateFileID(const wstring &file, DWORD id) {
- unordered_map<wstring, DWORD>::iterator iter = unique_files_.find(file);
- if (iter != unique_files_.end()) {
- // map this id to the previously seen one
- file_ids_[id] = iter->second;
- }
- }
-
- // Given a file's unique ID, return the ID that should be used to
- // reference it. There may be multiple files with identical filenames
- // but different unique IDs. The cache attempts to coalesce these into
- // one ID per unique filename.
- DWORD GetRealFileID(DWORD id) {
- unordered_map<DWORD, DWORD>::iterator iter = file_ids_.find(id);
- if (iter == file_ids_.end())
- return id;
- return iter->second;
- }
-
- // Find the PE file corresponding to the loaded PDB file, and
- // set the code_file_ member. Returns false on failure.
- bool FindPEFile();
-
- // Returns the function name for a symbol. If possible, the name is
- // undecorated. If the symbol's decorated form indicates the size of
- // parameters on the stack, this information is returned in stack_param_size.
- // Returns true on success. If the symbol doesn't encode parameter size
- // information, stack_param_size is set to -1.
- static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name,
- int *stack_param_size);
-
- // Returns the number of bytes of stack space used for a function's
- // parameters. function must have the tag SymTagFunction. In the event of
- // a failure, returns 0, which is also a valid number of bytes.
- static int GetFunctionStackParamSize(IDiaSymbol *function);
-
- // The filename of the PE file corresponding to the currently-open
- // pdb file.
- wstring code_file_;
-
- // The session for the currently-open pdb file.
- CComPtr<IDiaSession> session_;
-
- // The current output file for this WriteMap invocation.
- FILE *output_;
-
- // There may be many duplicate filenames with different IDs.
- // This maps from the DIA "unique ID" to a single ID per unique
- // filename.
- unordered_map<DWORD, DWORD> file_ids_;
- // This maps unique filenames to file IDs.
- unordered_map<wstring, DWORD> unique_files_;
-
- // This is used for calculating post-transform symbol addresses and lengths.
- ImageMap image_map_;
-
- // Disallow copy ctor and operator=
- PDBSourceLineWriter(const PDBSourceLineWriter&);
- void operator=(const PDBSourceLineWriter&);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
deleted file mode 100644
index 9b6360726..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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.
-
-// string_utils-inl.h: Safer string manipulation on Windows, supporting
-// pre-MSVC8 environments.
-
-#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H_
-#define COMMON_WINDOWS_STRING_UTILS_INL_H_
-
-#include <stdarg.h>
-#include <wchar.h>
-
-#include <string>
-
-// The "ll" printf format size specifier corresponding to |long long| was
-// intrudced in MSVC8. Earlier versions did not provide this size specifier,
-// but "I64" can be used to print 64-bit types. Don't use "I64" where "ll"
-// is available, in the event of oddball systems where |long long| is not
-// 64 bits wide.
-#if _MSC_VER >= 1400 // MSVC 2005/8
-#define WIN_STRING_FORMAT_LL "ll"
-#else // MSC_VER >= 1400
-#define WIN_STRING_FORMAT_LL "I64"
-#endif // MSC_VER >= 1400
-
-// A nonconforming version of swprintf, without the length argument, was
-// included with the CRT prior to MSVC8. Although a conforming version was
-// also available via an overload, it is not reliably chosen. _snwprintf
-// behaves as a standards-confirming swprintf should, so force the use of
-// _snwprintf when using older CRTs.
-#if _MSC_VER < 1400 // MSVC 2005/8
-#define swprintf _snwprintf
-#else
-// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently,
-// it takes the same argument list as swprintf.
-#define swprintf swprintf_s
-#endif // MSC_VER < 1400
-
-namespace google_breakpad {
-
-using std::string;
-using std::wstring;
-
-class WindowsStringUtils {
- public:
- // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does
- // not fail if source is longer than destination_size. The destination
- // buffer is always 0-terminated.
- static void safe_wcscpy(wchar_t *destination, size_t destination_size,
- const wchar_t *source);
-
- // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot
- // be passed directly, and pre-MSVC8, this will not fail if source or count
- // are longer than destination_size. The destination buffer is always
- // 0-terminated.
- static void safe_wcsncpy(wchar_t *destination, size_t destination_size,
- const wchar_t *source, size_t count);
-
- // Performs multi-byte to wide character conversion on C++ strings, using
- // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8). Returns false on failure,
- // without setting wcs.
- static bool safe_mbstowcs(const string &mbs, wstring *wcs);
-
- // The inverse of safe_mbstowcs.
- static bool safe_wcstombs(const wstring &wcs, string *mbs);
-
- // Returns the base name of a file, e.g. strips off the path.
- static wstring GetBaseName(const wstring &filename);
-
- private:
- // Disallow instantiation and other object-based operations.
- WindowsStringUtils();
- WindowsStringUtils(const WindowsStringUtils&);
- ~WindowsStringUtils();
- void operator=(const WindowsStringUtils&);
-};
-
-// static
-inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination,
- size_t destination_size,
- const wchar_t *source) {
-#if _MSC_VER >= 1400 // MSVC 2005/8
- wcscpy_s(destination, destination_size, source);
-#else // _MSC_VER >= 1400
- // Pre-MSVC 2005/8 doesn't have wcscpy_s. Simulate it with wcsncpy.
- // wcsncpy doesn't 0-terminate the destination buffer if the source string
- // is longer than size. Ensure that the destination is 0-terminated.
- wcsncpy(destination, source, destination_size);
- if (destination && destination_size)
- destination[destination_size - 1] = 0;
-#endif // _MSC_VER >= 1400
-}
-
-// static
-inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination,
- size_t destination_size,
- const wchar_t *source,
- size_t count) {
-#if _MSC_VER >= 1400 // MSVC 2005/8
- wcsncpy_s(destination, destination_size, source, count);
-#else // _MSC_VER >= 1400
- // Pre-MSVC 2005/8 doesn't have wcsncpy_s. Simulate it with wcsncpy.
- // wcsncpy doesn't 0-terminate the destination buffer if the source string
- // is longer than size. Ensure that the destination is 0-terminated.
- if (destination_size < count)
- count = destination_size;
-
- wcsncpy(destination, source, count);
- if (destination && count)
- destination[count - 1] = 0;
-#endif // _MSC_VER >= 1400
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_STRING_UTILS_INL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
deleted file mode 100644
index 272800035..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// 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.
-
-#include <cassert>
-#include <vector>
-
-#include "common/windows/string_utils-inl.h"
-
-namespace google_breakpad {
-
-// static
-wstring WindowsStringUtils::GetBaseName(const wstring &filename) {
- wstring base_name(filename);
- size_t slash_pos = base_name.find_last_of(L"/\\");
- if (slash_pos != wstring::npos) {
- base_name.erase(0, slash_pos + 1);
- }
- return base_name;
-}
-
-// static
-bool WindowsStringUtils::safe_mbstowcs(const string &mbs, wstring *wcs) {
- assert(wcs);
-
- // First, determine the length of the destination buffer.
- size_t wcs_length;
-
-#if _MSC_VER >= 1400 // MSVC 2005/8
- errno_t err;
- if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) {
- return false;
- }
- assert(wcs_length > 0);
-#else // _MSC_VER >= 1400
- if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) == (size_t)-1) {
- return false;
- }
-
- // Leave space for the 0-terminator.
- ++wcs_length;
-#endif // _MSC_VER >= 1400
-
- std::vector<wchar_t> wcs_v(wcs_length);
-
- // Now, convert.
-#if _MSC_VER >= 1400 // MSVC 2005/8
- if ((err = mbstowcs_s(NULL, &wcs_v[0], wcs_length, mbs.c_str(),
- _TRUNCATE)) != 0) {
- return false;
- }
-#else // _MSC_VER >= 1400
- if (mbstowcs(&wcs_v[0], mbs.c_str(), mbs.length()) == (size_t)-1) {
- return false;
- }
-
- // Ensure presence of 0-terminator.
- wcs_v[wcs_length - 1] = '\0';
-#endif // _MSC_VER >= 1400
-
- *wcs = &wcs_v[0];
- return true;
-}
-
-// static
-bool WindowsStringUtils::safe_wcstombs(const wstring &wcs, string *mbs) {
- assert(mbs);
-
- // First, determine the length of the destination buffer.
- size_t mbs_length;
-
-#if _MSC_VER >= 1400 // MSVC 2005/8
- errno_t err;
- if ((err = wcstombs_s(&mbs_length, NULL, 0, wcs.c_str(), _TRUNCATE)) != 0) {
- return false;
- }
- assert(mbs_length > 0);
-#else // _MSC_VER >= 1400
- if ((mbs_length = wcstombs(NULL, wcs.c_str(), wcs.length())) == (size_t)-1) {
- return false;
- }
-
- // Leave space for the 0-terminator.
- ++mbs_length;
-#endif // _MSC_VER >= 1400
-
- std::vector<char> mbs_v(mbs_length);
-
- // Now, convert.
-#if _MSC_VER >= 1400 // MSVC 2005/8
- if ((err = wcstombs_s(NULL, &mbs_v[0], mbs_length, wcs.c_str(),
- _TRUNCATE)) != 0) {
- return false;
- }
-#else // _MSC_VER >= 1400
- if (wcstombs(&mbs_v[0], wcs.c_str(), wcs.length()) == (size_t)-1) {
- return false;
- }
-
- // Ensure presence of 0-terminator.
- mbs_v[mbs_length - 1] = '\0';
-#endif // _MSC_VER >= 1400
-
- *mbs = &mbs_v[0];
- return true;
-}
-
-} // namespace google_breakpad