summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/breakpad-client/mac
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/breakpad-client/mac')
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h47
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc74
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h66
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc164
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h151
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build18
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc402
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h48
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc625
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h386
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc990
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h297
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h88
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc2135
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h290
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj843
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/moz.build22
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc92
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h85
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc79
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h52
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc106
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h62
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h46
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm60
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_databin0 -> 702795 bytes
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym5300
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h47
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm217
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc398
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc714
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc320
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc74
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h149
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h9
35 files changed, 14456 insertions, 0 deletions
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h
new file mode 100644
index 0000000000..a3a95dcace
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
+#define CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
+
+namespace google_breakpad {
+
+class ClientInfo {
+ public:
+ explicit ClientInfo(pid_t pid) : pid_(pid) {}
+
+ pid_t pid() const { return pid_; }
+
+ private:
+ pid_t pid_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
new file mode 100644
index 0000000000..bdbf43aaca
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010 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 "mac/crash_generation/crash_generation_client.h"
+
+#include "mac/crash_generation/crash_generation_server.h"
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+bool CrashGenerationClient::RequestDumpForException(
+ int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t crashing_thread,
+ mach_port_t crashing_task) {
+ // The server will send a message to this port indicating that it
+ // has finished its work.
+ ReceivePort acknowledge_port;
+
+ MachSendMessage message(kDumpRequestMessage);
+ message.AddDescriptor(crashing_task); // crashing task
+ message.AddDescriptor(crashing_thread); // crashing thread
+ message.AddDescriptor(MACH_PORT_NULL); // handler thread
+ message.AddDescriptor(acknowledge_port.GetPort()); // message receive port
+
+ ExceptionInfo info;
+ info.exception_type = exception_type;
+ info.exception_code = exception_code;
+ info.exception_subcode = exception_subcode;
+ info.child_pid = getpid();
+
+ message.SetData(&info, sizeof(info));
+
+ kern_return_t result = sender_.SendMessage(message, MACH_MSG_TIMEOUT_NONE);
+ if (result != KERN_SUCCESS)
+ return false;
+
+ // Give the server slightly longer to reply since it has to
+ // inspect this task and write the minidump.
+ MachReceiveMessage acknowledge_message;
+ result = acknowledge_port.WaitForMessage(&acknowledge_message,
+ MACH_MSG_TIMEOUT_NONE);
+
+ return result == KERN_SUCCESS;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h
new file mode 100644
index 0000000000..9bcd79af7f
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+#define GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+class CrashGenerationClient {
+ public:
+ explicit CrashGenerationClient(const char* mach_port_name)
+ : sender_(mach_port_name) {
+ }
+
+ // Request the crash server to generate a dump.
+ //
+ // Return true if the dump was successful; false otherwise.
+ bool RequestDumpForException(int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t crashing_thread,
+ mach_port_t crashing_task);
+
+ bool RequestDump() {
+ return RequestDumpForException(0, 0, 0, MACH_PORT_NULL, mach_task_self());
+ }
+
+ private:
+ MachPortSender sender_;
+
+ // Prevent copy construction and assignment.
+ CrashGenerationClient(const CrashGenerationClient&);
+ CrashGenerationClient& operator=(const CrashGenerationClient&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
new file mode 100644
index 0000000000..b7b9b5881e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
@@ -0,0 +1,164 @@
+// Copyright (c) 2010 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 "mac/crash_generation/crash_generation_server.h"
+
+#include <pthread.h>
+
+#include "mac/crash_generation/client_info.h"
+#include "mac/handler/minidump_generator.h"
+#include "common/mac/scoped_task_suspend-inl.h"
+
+namespace google_breakpad {
+
+CrashGenerationServer::CrashGenerationServer(
+ const char *mach_port_name,
+ FilterCallback filter,
+ void *filter_context,
+ OnClientDumpRequestCallback dump_callback,
+ void *dump_context,
+ OnClientExitingCallback exit_callback,
+ void *exit_context,
+ bool generate_dumps,
+ const std::string &dump_path)
+ : filter_(filter),
+ filter_context_(filter_context),
+ dump_callback_(dump_callback),
+ dump_context_(dump_context),
+ exit_callback_(exit_callback),
+ exit_context_(exit_context),
+ generate_dumps_(generate_dumps),
+ dump_dir_(dump_path.empty() ? "/tmp" : dump_path),
+ started_(false),
+ receive_port_(mach_port_name),
+ mach_port_name_(mach_port_name) {
+}
+
+CrashGenerationServer::~CrashGenerationServer() {
+ if (started_)
+ Stop();
+}
+
+bool CrashGenerationServer::Start() {
+ int thread_create_result = pthread_create(&server_thread_, NULL,
+ &WaitForMessages, this);
+ started_ = thread_create_result == 0;
+ return started_;
+}
+
+bool CrashGenerationServer::Stop() {
+ if (!started_)
+ return false;
+
+ // Send a quit message to the background thread, and then join it.
+ MachPortSender sender(mach_port_name_.c_str());
+ MachSendMessage quit_message(kQuitMessage);
+ const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
+ kern_return_t result = sender.SendMessage(quit_message, kSendTimeoutMs);
+ if (result == KERN_SUCCESS) {
+ int thread_join_result = pthread_join(server_thread_, NULL);
+ started_ = thread_join_result != 0;
+ }
+
+ return !started_;
+}
+
+// static
+void *CrashGenerationServer::WaitForMessages(void *server) {
+ pthread_setname_np("Breakpad CrashGenerationServer");
+
+ CrashGenerationServer *self =
+ reinterpret_cast<CrashGenerationServer*>(server);
+ while (self->WaitForOneMessage()) {}
+ return NULL;
+}
+
+bool CrashGenerationServer::WaitForOneMessage() {
+ MachReceiveMessage message;
+ kern_return_t result = receive_port_.WaitForMessage(&message,
+ MACH_MSG_TIMEOUT_NONE);
+ if (result == KERN_SUCCESS) {
+ switch (message.GetMessageID()) {
+ case kDumpRequestMessage: {
+ ExceptionInfo &info = (ExceptionInfo &)*message.GetData();
+
+ mach_port_t remote_task = message.GetTranslatedPort(0);
+ mach_port_t crashing_thread = message.GetTranslatedPort(1);
+ mach_port_t handler_thread = message.GetTranslatedPort(2);
+ mach_port_t ack_port = message.GetTranslatedPort(3);
+ ClientInfo client(info.child_pid);
+
+ bool result;
+ std::string dump_path;
+ if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
+ ScopedTaskSuspend suspend(remote_task);
+
+ MinidumpGenerator generator(remote_task, handler_thread);
+ dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL);
+
+ if (info.exception_type && info.exception_code) {
+ generator.SetExceptionInformation(info.exception_type,
+ info.exception_code,
+ info.exception_subcode,
+ crashing_thread);
+ }
+ result = generator.Write(dump_path.c_str());
+ } else {
+ result = true;
+ }
+
+ if (result && dump_callback_) {
+ dump_callback_(dump_context_, client, dump_path);
+ }
+
+ // TODO(ted): support a way for the client to send additional data,
+ // perhaps with a callback so users of the server can read the data
+ // themselves?
+
+ if (ack_port != MACH_PORT_DEAD && ack_port != MACH_PORT_NULL) {
+ MachPortSender sender(ack_port);
+ MachSendMessage ack_message(kAcknowledgementMessage);
+ sender.SendMessage(ack_message, MACH_MSG_TIMEOUT_NONE);
+ }
+
+ if (result && exit_callback_) {
+ exit_callback_(exit_context_, client);
+ }
+ break;
+ }
+ case kQuitMessage:
+ return false;
+ }
+ } else { // result != KERN_SUCCESS
+ return false;
+ }
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
new file mode 100644
index 0000000000..d0b39f3acf
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+#define GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+class ClientInfo;
+
+// Messages the server can read via its mach port
+enum {
+ kDumpRequestMessage = 1,
+ kAcknowledgementMessage = 2,
+ kQuitMessage = 3
+};
+
+// Exception details sent by the client when requesting a dump.
+struct ExceptionInfo {
+ int32_t exception_type;
+ int32_t exception_code;
+ int64_t exception_subcode;
+ int32_t child_pid;
+};
+
+class CrashGenerationServer {
+ public:
+ // WARNING: callbacks may be invoked on a different thread
+ // than that which creates the CrashGenerationServer. They must
+ // be thread safe.
+ typedef void (*OnClientDumpRequestCallback)(void *context,
+ const ClientInfo &client_info,
+ const std::string &file_path);
+
+ typedef void (*OnClientExitingCallback)(void *context,
+ const ClientInfo &client_info);
+ // If a FilterCallback returns false, the dump will not be written.
+ typedef bool (*FilterCallback)(void *context);
+
+ // Create an instance with the given parameters.
+ //
+ // mach_port_name: Named server port to listen on.
+ // filter: Callback for a client to cancel writing a dump.
+ // filter_context: Context for the filter callback.
+ // dump_callback: Callback for a client crash dump request.
+ // dump_context: Context for client crash dump request callback.
+ // exit_callback: Callback for client process exit.
+ // exit_context: Context for client exit callback.
+ // generate_dumps: Whether to automatically generate dumps.
+ // Client code of this class might want to generate dumps explicitly
+ // in the crash dump request callback. In that case, false can be
+ // passed for this parameter.
+ // dump_path: Path for generating dumps; required only if true is
+ // passed for generateDumps parameter; NULL can be passed otherwise.
+ CrashGenerationServer(const char *mach_port_name,
+ FilterCallback filter,
+ void *filter_context,
+ OnClientDumpRequestCallback dump_callback,
+ void *dump_context,
+ OnClientExitingCallback exit_callback,
+ void *exit_context,
+ bool generate_dumps,
+ const std::string &dump_path);
+
+ ~CrashGenerationServer();
+
+ // Perform initialization steps needed to start listening to clients.
+ //
+ // Return true if initialization is successful; false otherwise.
+ bool Start();
+
+ // Stop the server.
+ bool Stop();
+
+ private:
+ // Return a unique filename at which a minidump can be written.
+ bool MakeMinidumpFilename(std::string &outFilename);
+
+ // Loop reading client messages and responding to them until
+ // a quit message is received.
+ static void *WaitForMessages(void *server);
+
+ // Wait for a single client message and respond to it. Returns false
+ // if a quit message was received or if an error occurred.
+ bool WaitForOneMessage();
+
+ FilterCallback filter_;
+ void *filter_context_;
+
+ OnClientDumpRequestCallback dump_callback_;
+ void *dump_context_;
+
+ OnClientExitingCallback exit_callback_;
+ void *exit_context_;
+
+ bool generate_dumps_;
+
+ std::string dump_dir_;
+
+ bool started_;
+
+ // The mach port that receives requests to dump from child processes.
+ ReceivePort receive_port_;
+
+ // The name of the mach port. Stored so the Stop method can message
+ // the background thread to shut it down.
+ std::string mach_port_name_;
+
+ // The thread that waits on the receive port.
+ pthread_t server_thread_;
+
+ // Disable copy constructor and operator=.
+ CrashGenerationServer(const CrashGenerationServer&);
+ CrashGenerationServer& operator=(const CrashGenerationServer&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
new file mode 100644
index 0000000000..731670a4f1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
@@ -0,0 +1,18 @@
+# -*- 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/.
+
+UNIFIED_SOURCES += [
+ 'crash_generation_client.cc',
+ 'crash_generation_server.cc',
+]
+
+FINAL_LIBRARY = 'breakpad_client'
+
+LOCAL_INCLUDES += [
+ '/ipc/chromium/src',
+ '/toolkit/crashreporter/breakpad-client',
+ '/toolkit/crashreporter/google-breakpad/src',
+]
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc
new file mode 100644
index 0000000000..3492b823da
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 file was copied from libc/gen/nlist.c from Darwin's source code
+ * The version of nlist used as a base is from 10.5.2, libc-498
+ * http://www.opensource.apple.com/darwinsource/10.5.2/Libc-498/gen/nlist.c
+ *
+ * The full tarball is at:
+ * http://www.opensource.apple.com/darwinsource/tarballs/apsl/Libc-498.tar.gz
+ *
+ * I've modified it to be compatible with 64-bit images.
+*/
+
+#include "breakpad_nlist_64.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <fcntl.h>
+#include <mach-o/nlist.h>
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach/mach.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <TargetConditionals.h>
+#include <unistd.h>
+
+/* Stuff lifted from <a.out.h> and <sys/exec.h> since they are gone */
+/*
+ * Header prepended to each a.out file.
+ */
+struct exec {
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_magic; /* magic number */
+ unsigned long a_text; /* size of text segment */
+ unsigned long a_data; /* size of initialized data */
+ unsigned long a_bss; /* size of uninitialized data */
+ unsigned long a_syms; /* size of symbol table */
+ unsigned long a_entry; /* entry point */
+ unsigned long a_trsize; /* size of text relocation */
+ unsigned long a_drsize; /* size of data relocation */
+};
+
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+#define N_BADMAG(x) \
+ (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+#define N_TXTOFF(x) \
+ ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec))
+#define N_SYMOFF(x) \
+ (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize)
+
+// Traits structs for specializing function templates to handle
+// 32-bit/64-bit Mach-O files.
+template<typename T>
+struct MachBits {};
+
+typedef struct nlist nlist32;
+typedef struct nlist_64 nlist64;
+
+template<>
+struct MachBits<nlist32> {
+ typedef mach_header mach_header_type;
+ typedef uint32_t word_type;
+ static const uint32_t magic = MH_MAGIC;
+};
+
+template<>
+struct MachBits<nlist64> {
+ typedef mach_header_64 mach_header_type;
+ typedef uint64_t word_type;
+ static const uint32_t magic = MH_MAGIC_64;
+};
+
+template<typename nlist_type>
+int
+__breakpad_fdnlist(int fd, nlist_type *list, const char **symbolNames,
+ cpu_type_t cpu_type);
+
+/*
+ * nlist - retreive attributes from name list (string table version)
+ */
+
+template <typename nlist_type>
+int breakpad_nlist_common(const char *name,
+ nlist_type *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ int fd = open(name, O_RDONLY, 0);
+ if (fd < 0)
+ return -1;
+ int n = __breakpad_fdnlist(fd, list, symbolNames, cpu_type);
+ close(fd);
+ return n;
+}
+
+int breakpad_nlist(const char *name,
+ struct nlist *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ return breakpad_nlist_common(name, list, symbolNames, cpu_type);
+}
+
+int breakpad_nlist(const char *name,
+ struct nlist_64 *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ return breakpad_nlist_common(name, list, symbolNames, cpu_type);
+}
+
+/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */
+
+template<typename nlist_type>
+int __breakpad_fdnlist(int fd, nlist_type *list, const char **symbolNames,
+ cpu_type_t cpu_type) {
+ typedef typename MachBits<nlist_type>::mach_header_type mach_header_type;
+ typedef typename MachBits<nlist_type>::word_type word_type;
+
+ const uint32_t magic = MachBits<nlist_type>::magic;
+
+ int maxlen = 500;
+ int nreq = 0;
+ for (nlist_type* q = list;
+ symbolNames[q-list] && symbolNames[q-list][0];
+ q++, nreq++) {
+
+ q->n_type = 0;
+ q->n_value = 0;
+ q->n_desc = 0;
+ q->n_sect = 0;
+ q->n_un.n_strx = 0;
+ }
+
+ struct exec buf;
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) ||
+ (N_BADMAG(buf) && *((uint32_t *)&buf) != magic &&
+ CFSwapInt32BigToHost(*((uint32_t *)&buf)) != FAT_MAGIC &&
+ /* The following is the big-endian ppc64 check */
+ (*((uint32_t*)&buf)) != FAT_MAGIC)) {
+ return -1;
+ }
+
+ /* Deal with fat file if necessary */
+ unsigned arch_offset = 0;
+ if (CFSwapInt32BigToHost(*((uint32_t *)&buf)) == FAT_MAGIC ||
+ /* The following is the big-endian ppc64 check */
+ *((unsigned int *)&buf) == FAT_MAGIC) {
+ /* Read in the fat header */
+ struct fat_header fh;
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) {
+ return -1;
+ }
+
+ /* Convert fat_narchs to host byte order */
+ fh.nfat_arch = CFSwapInt32BigToHost(fh.nfat_arch);
+
+ /* Read in the fat archs */
+ struct fat_arch *fat_archs =
+ (struct fat_arch *)malloc(fh.nfat_arch * sizeof(struct fat_arch));
+ if (fat_archs == NULL) {
+ return -1;
+ }
+ if (read(fd, (char *)fat_archs,
+ sizeof(struct fat_arch) * fh.nfat_arch) !=
+ (ssize_t)(sizeof(struct fat_arch) * fh.nfat_arch)) {
+ free(fat_archs);
+ return -1;
+ }
+
+ /*
+ * Convert archs to host byte ordering (a constraint of
+ * cpusubtype_getbestarch()
+ */
+ for (unsigned i = 0; i < fh.nfat_arch; i++) {
+ fat_archs[i].cputype =
+ CFSwapInt32BigToHost(fat_archs[i].cputype);
+ fat_archs[i].cpusubtype =
+ CFSwapInt32BigToHost(fat_archs[i].cpusubtype);
+ fat_archs[i].offset =
+ CFSwapInt32BigToHost(fat_archs[i].offset);
+ fat_archs[i].size =
+ CFSwapInt32BigToHost(fat_archs[i].size);
+ fat_archs[i].align =
+ CFSwapInt32BigToHost(fat_archs[i].align);
+ }
+
+ struct fat_arch *fap = NULL;
+ for (unsigned i = 0; i < fh.nfat_arch; i++) {
+ if (fat_archs[i].cputype == cpu_type) {
+ fap = &fat_archs[i];
+ break;
+ }
+ }
+
+ if (!fap) {
+ free(fat_archs);
+ return -1;
+ }
+ arch_offset = fap->offset;
+ free(fat_archs);
+
+ /* Read in the beginning of the architecture-specific file */
+ if (lseek(fd, arch_offset, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) {
+ return -1;
+ }
+ }
+
+ off_t sa; /* symbol address */
+ off_t ss; /* start of strings */
+ register_t n;
+ if (*((unsigned int *)&buf) == magic) {
+ if (lseek(fd, arch_offset, SEEK_SET) == -1) {
+ return -1;
+ }
+ mach_header_type mh;
+ if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) {
+ return -1;
+ }
+
+ struct load_command *load_commands =
+ (struct load_command *)malloc(mh.sizeofcmds);
+ if (load_commands == NULL) {
+ return -1;
+ }
+ if (read(fd, (char *)load_commands, mh.sizeofcmds) !=
+ (ssize_t)mh.sizeofcmds) {
+ free(load_commands);
+ return -1;
+ }
+ struct symtab_command *stp = NULL;
+ struct load_command *lcp = load_commands;
+ // iterate through all load commands, looking for
+ // LC_SYMTAB load command
+ for (uint32_t i = 0; i < mh.ncmds; i++) {
+ if (lcp->cmdsize % sizeof(word_type) != 0 ||
+ lcp->cmdsize <= 0 ||
+ (char *)lcp + lcp->cmdsize >
+ (char *)load_commands + mh.sizeofcmds) {
+ free(load_commands);
+ return -1;
+ }
+ if (lcp->cmd == LC_SYMTAB) {
+ if (lcp->cmdsize !=
+ sizeof(struct symtab_command)) {
+ free(load_commands);
+ return -1;
+ }
+ stp = (struct symtab_command *)lcp;
+ break;
+ }
+ lcp = (struct load_command *)
+ ((char *)lcp + lcp->cmdsize);
+ }
+ if (stp == NULL) {
+ free(load_commands);
+ return -1;
+ }
+ // sa points to the beginning of the symbol table
+ sa = stp->symoff + arch_offset;
+ // ss points to the beginning of the string table
+ ss = stp->stroff + arch_offset;
+ // n is the number of bytes in the symbol table
+ // each symbol table entry is an nlist structure
+ n = stp->nsyms * sizeof(nlist_type);
+ free(load_commands);
+ } else {
+ sa = N_SYMOFF(buf) + arch_offset;
+ ss = sa + buf.a_syms + arch_offset;
+ n = buf.a_syms;
+ }
+
+ if (lseek(fd, sa, SEEK_SET) == -1) {
+ return -1;
+ }
+
+ // the algorithm here is to read the nlist entries in m-sized
+ // chunks into q. q is then iterated over. for each entry in q,
+ // use the string table index(q->n_un.n_strx) to read the symbol
+ // name, then scan the nlist entries passed in by the user(via p),
+ // and look for a match
+ while (n) {
+ nlist_type space[BUFSIZ/sizeof (nlist_type)];
+ register_t m = sizeof (space);
+
+ if (n < m)
+ m = n;
+ if (read(fd, (char *)space, m) != m)
+ break;
+ n -= m;
+ off_t savpos = lseek(fd, 0, SEEK_CUR);
+ if (savpos == -1) {
+ return -1;
+ }
+ for (nlist_type* q = space; (m -= sizeof(nlist_type)) >= 0; q++) {
+ char nambuf[BUFSIZ];
+
+ if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
+ continue;
+
+ // seek to the location in the binary where the symbol
+ // name is stored & read it into memory
+ if (lseek(fd, ss+q->n_un.n_strx, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, nambuf, maxlen+1) == -1) {
+ return -1;
+ }
+ const char *s2 = nambuf;
+ for (nlist_type *p = list;
+ symbolNames[p-list] && symbolNames[p-list][0];
+ p++) {
+ // get the symbol name the user has passed in that
+ // corresponds to the nlist entry that we're looking at
+ const char *s1 = symbolNames[p - list];
+ while (*s1) {
+ if (*s1++ != *s2++)
+ goto cont;
+ }
+ if (*s2)
+ goto cont;
+
+ p->n_value = q->n_value;
+ p->n_type = q->n_type;
+ p->n_desc = q->n_desc;
+ p->n_sect = q->n_sect;
+ p->n_un.n_strx = q->n_un.n_strx;
+ if (--nreq == 0)
+ return nreq;
+
+ break;
+ cont: ;
+ }
+ }
+ if (lseek(fd, savpos, SEEK_SET) == -1) {
+ return -1;
+ }
+ }
+ return nreq;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
new file mode 100644
index 0000000000..e8e2e0834e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2008, 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.
+
+// breakpad_nlist.h
+//
+// This file is meant to provide a header for clients of the modified
+// nlist function implemented to work on 64-bit.
+
+#ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+#define CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+
+#include <mach/machine.h>
+
+int breakpad_nlist(const char *name,
+ struct nlist *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type);
+int breakpad_nlist(const char *name,
+ struct nlist_64 *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type);
+
+#endif /* CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ */
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc
new file mode 100644
index 0000000000..855580a071
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc
@@ -0,0 +1,625 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "mac/handler/dynamic_images.h"
+
+extern "C" { // needed to compile on Leopard
+ #include <mach-o/nlist.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+}
+
+#include <assert.h>
+#include <AvailabilityMacros.h>
+#include <dlfcn.h>
+#include <mach/task_info.h>
+#include <sys/sysctl.h>
+#include <TargetConditionals.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "breakpad_nlist_64.h"
+
+#if !TARGET_OS_IPHONE
+#include <CoreServices/CoreServices.h>
+#endif // !TARGET_OS_IPHONE
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+//==============================================================================
+// Returns the size of the memory region containing |address| and the
+// number of bytes from |address| to the end of the region.
+// We potentially, will extend the size of the original
+// region by the size of the following region if it's contiguous with the
+// first in order to handle cases when we're reading strings and they
+// straddle two vm regions.
+//
+static mach_vm_size_t GetMemoryRegionSize(task_port_t target_task,
+ const uint64_t address,
+ mach_vm_size_t *size_to_end) {
+ mach_vm_address_t region_base = (mach_vm_address_t)address;
+ mach_vm_size_t region_size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ // Get information about the vm region containing |address|
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
+
+ kern_return_t result =
+ mach_vm_region_recurse(target_task,
+ &region_base,
+ &region_size,
+ &nesting_level,
+ region_info,
+ &info_count);
+
+ if (result == KERN_SUCCESS) {
+ // Get distance from |address| to the end of this region
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
+
+ // If we want to handle strings as long as 4096 characters we may need
+ // to check if there's a vm region immediately following the first one.
+ // If so, we need to extend |*size_to_end| to go all the way to the end
+ // of the second region.
+ if (*size_to_end < 4096) {
+ // Second region starts where the first one ends
+ mach_vm_address_t region_base2 =
+ (mach_vm_address_t)(region_base + region_size);
+ mach_vm_size_t region_size2;
+
+ // Get information about the following vm region
+ result =
+ mach_vm_region_recurse(target_task,
+ &region_base2,
+ &region_size2,
+ &nesting_level,
+ region_info,
+ &info_count);
+
+ // Extend region_size to go all the way to the end of the 2nd region
+ if (result == KERN_SUCCESS
+ && region_base2 == region_base + region_size) {
+ region_size += region_size2;
+ }
+ }
+
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
+ } else {
+ region_size = 0;
+ *size_to_end = 0;
+ }
+
+ return region_size;
+}
+
+#define kMaxStringLength 8192
+//==============================================================================
+// Reads a NULL-terminated string from another task.
+//
+// Warning! This will not read any strings longer than kMaxStringLength-1
+//
+string ReadTaskString(task_port_t target_task,
+ const uint64_t address) {
+ // The problem is we don't know how much to read until we know how long
+ // the string is. And we don't know how long the string is, until we've read
+ // the memory! So, we'll try to read kMaxStringLength bytes
+ // (or as many bytes as we can until we reach the end of the vm region).
+ mach_vm_size_t size_to_end;
+ GetMemoryRegionSize(target_task, address, &size_to_end);
+
+ if (size_to_end > 0) {
+ mach_vm_size_t size_to_read =
+ size_to_end > kMaxStringLength ? kMaxStringLength : size_to_end;
+
+ vector<uint8_t> bytes;
+ if (ReadTaskMemory(target_task, address, (size_t)size_to_read, bytes) !=
+ KERN_SUCCESS)
+ return string();
+
+ return string(reinterpret_cast<const char*>(&bytes[0]));
+ }
+
+ return string();
+}
+
+//==============================================================================
+// Reads an address range from another task. The bytes read will be returned
+// in bytes, which will be resized as necessary.
+kern_return_t ReadTaskMemory(task_port_t target_task,
+ const uint64_t address,
+ size_t length,
+ vector<uint8_t> &bytes) {
+ int systemPageSize = getpagesize();
+
+ // use the negative of the page size for the mask to find the page address
+ mach_vm_address_t page_address = address & (-systemPageSize);
+
+ mach_vm_address_t last_page_address =
+ (address + length + (systemPageSize - 1)) & (-systemPageSize);
+
+ mach_vm_size_t page_size = last_page_address - page_address;
+ uint8_t* local_start;
+ uint32_t local_length;
+
+ kern_return_t r = mach_vm_read(target_task,
+ page_address,
+ page_size,
+ reinterpret_cast<vm_offset_t*>(&local_start),
+ &local_length);
+
+ if (r != KERN_SUCCESS)
+ return r;
+
+ bytes.resize(length);
+ memcpy(&bytes[0],
+ &local_start[(mach_vm_address_t)address - page_address],
+ length);
+ mach_vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_length);
+ return KERN_SUCCESS;
+}
+
+#pragma mark -
+
+//==============================================================================
+// Traits structs for specializing function templates to handle
+// 32-bit/64-bit Mach-O files.
+struct MachO32 {
+ typedef mach_header mach_header_type;
+ typedef segment_command mach_segment_command_type;
+ typedef dyld_image_info32 dyld_image_info;
+ typedef dyld_all_image_infos32 dyld_all_image_infos;
+ typedef section mach_section_type;
+ typedef struct nlist nlist_type;
+ static const uint32_t magic = MH_MAGIC;
+ static const uint32_t segment_load_command = LC_SEGMENT;
+};
+
+struct MachO64 {
+ typedef mach_header_64 mach_header_type;
+ typedef segment_command_64 mach_segment_command_type;
+ typedef dyld_image_info64 dyld_image_info;
+ typedef dyld_all_image_infos64 dyld_all_image_infos;
+ typedef section_64 mach_section_type;
+ typedef struct nlist_64 nlist_type;
+ static const uint32_t magic = MH_MAGIC_64;
+ static const uint32_t segment_load_command = LC_SEGMENT_64;
+};
+
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+ typedef typename MachBits::mach_segment_command_type
+ mach_segment_command_type;
+ typedef typename MachBits::mach_section_type mach_section_type;
+
+ const mach_header_type* header =
+ reinterpret_cast<const mach_header_type*>(&image.header_[0]);
+
+ if(header->magic != MachBits::magic) {
+ return false;
+ }
+
+ bool is_in_shared_cache = ((header->flags & MH_SHAREDCACHE) != 0);
+ if (is_in_shared_cache) {
+ image.slide_ = image.shared_cache_slide_;
+ }
+
+ const struct load_command *cmd =
+ reinterpret_cast<const struct load_command *>(header + 1);
+
+ bool retval = false;
+
+ uint32_t num_data_sections = 0;
+ const mach_section_type *data_sections = NULL;
+ uint32_t num_data_dirty_sections = 0;
+ const mach_section_type *data_dirty_sections = NULL;
+ bool found_text_section = false;
+ bool found_dylib_id_command = false;
+ for (unsigned int i = 0; cmd && (i < header->ncmds); ++i) {
+ if (!data_sections) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!strcmp(seg->segname, "__DATA")) {
+ num_data_sections = seg->nsects;
+ data_sections = reinterpret_cast<const mach_section_type *>(seg + 1);
+ }
+ }
+ }
+
+ if (!data_dirty_sections) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!strcmp(seg->segname, "__DATA_DIRTY")) {
+ num_data_dirty_sections = seg->nsects;
+ data_dirty_sections =
+ reinterpret_cast<const mach_section_type *>(seg + 1);
+ }
+ }
+ }
+
+ if (!found_text_section) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!is_in_shared_cache) {
+ if (seg->fileoff == 0 && seg->filesize != 0) {
+ image.slide_ =
+ (uintptr_t)image.GetLoadAddress() - (uintptr_t)seg->vmaddr;
+ }
+ }
+
+ if (!strcmp(seg->segname, "__TEXT")) {
+ image.vmaddr_ = static_cast<mach_vm_address_t>(seg->vmaddr);
+ image.vmsize_ = static_cast<mach_vm_size_t>(seg->vmsize);
+ found_text_section = true;
+ }
+ }
+ }
+
+ if (!found_dylib_id_command) {
+ if (cmd->cmd == LC_ID_DYLIB) {
+ const struct dylib_command *dc =
+ reinterpret_cast<const struct dylib_command *>(cmd);
+
+ image.version_ = dc->dylib.current_version;
+ found_dylib_id_command = true;
+ }
+ }
+
+ if (found_dylib_id_command && found_text_section &&
+ data_sections && data_dirty_sections) {
+ break;
+ }
+
+ cmd = reinterpret_cast<const struct load_command *>
+ (reinterpret_cast<const char *>(cmd) + cmd->cmdsize);
+ }
+
+ if (found_dylib_id_command && found_text_section) {
+ retval = true;
+ }
+
+ // The __DYLD,__crash_info section may not be accessible in child process
+ // modules that aren't dyld or in the dyld shared cache.
+ if (image.GetIsDyld() || is_in_shared_cache) {
+ for (unsigned int i = 0; i < num_data_sections; ++i) {
+ if (!strcmp(data_sections[i].sectname, "__crash_info")) {
+ ReadTaskMemory(image.task_,
+ data_sections[i].addr + image.slide_,
+ data_sections[i].size,
+ image.crash_info_);
+ return retval;
+ }
+ }
+ // __crash_info might be in the __DATA_DIRTY segment.
+ for (unsigned int i = 0; i < num_data_dirty_sections; ++i) {
+ if (!strcmp(data_dirty_sections[i].sectname, "__crash_info")) {
+ ReadTaskMemory(image.task_,
+ data_dirty_sections[i].addr + image.slide_,
+ data_dirty_sections[i].size,
+ image.crash_info_);
+ return retval;
+ }
+ }
+ }
+
+ return retval;
+}
+
+//==============================================================================
+// Initializes vmaddr_, vmsize_, and slide_
+void DynamicImage::CalculateMemoryAndVersionInfo() {
+ // unless we can process the header, ensure that calls to
+ // IsValid() will return false
+ vmaddr_ = 0;
+ vmsize_ = 0;
+ slide_ = 0;
+ version_ = 0;
+
+ // The function template above does all the real work.
+ if (Is64Bit())
+ FindTextSection<MachO64>(*this);
+ else
+ FindTextSection<MachO32>(*this);
+}
+
+//==============================================================================
+// The helper function template abstracts the 32/64-bit differences.
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+
+ const mach_header_type* header =
+ reinterpret_cast<const mach_header_type*>(&image.header_[0]);
+ return header->filetype;
+}
+
+uint32_t DynamicImage::GetFileType() {
+ if (Is64Bit())
+ return GetFileTypeFromHeader<MachO64>(*this);
+
+ return GetFileTypeFromHeader<MachO32>(*this);
+}
+
+#pragma mark -
+
+//==============================================================================
+// Loads information about dynamically loaded code in the given task.
+DynamicImages::DynamicImages(mach_port_t task)
+ : task_(task),
+ cpu_type_(DetermineTaskCPUType(task)),
+ image_list_() {
+ ReadImageInfoForTask();
+}
+
+template<typename MachBits>
+static uint64_t LookupSymbol(const char* symbol_name,
+ const char* filename,
+ cpu_type_t cpu_type) {
+ typedef typename MachBits::nlist_type nlist_type;
+
+ nlist_type symbol_info[8] = {};
+ const char *symbolNames[2] = { symbol_name, "\0" };
+ nlist_type &list = symbol_info[0];
+ int invalidEntriesCount = breakpad_nlist(filename,
+ &list,
+ symbolNames,
+ cpu_type);
+
+ if(invalidEntriesCount != 0) {
+ return 0;
+ }
+
+ assert(list.n_value);
+ return list.n_value;
+}
+
+uint64_t DynamicImages::GetDyldAllImageInfosPointer() {
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ if (task_info(task_, TASK_DYLD_INFO, (task_info_t)&task_dyld_info,
+ &count) != KERN_SUCCESS) {
+ return 0;
+ }
+
+ return (uint64_t)task_dyld_info.all_image_info_addr;
+}
+
+//==============================================================================
+// This code was written using dyld_debug.c (from Darwin) as a guide.
+
+template<typename MachBits>
+void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+
+ // First read just the mach_header from the image in the task.
+ vector<uint8_t> mach_header_bytes;
+ if (ReadTaskMemory(images.task_,
+ image_address,
+ sizeof(mach_header_type),
+ mach_header_bytes) != KERN_SUCCESS) {
+ return; // bail on this dynamic image
+ }
+
+ mach_header_type *header =
+ reinterpret_cast<mach_header_type*>(&mach_header_bytes[0]);
+ if (header->magic != MachBits::magic) {
+ return;
+ }
+
+ cpu_subtype_t cpusubtype = (header->cpusubtype & ~CPU_SUBTYPE_MASK);
+
+ // Now determine the total amount necessary to read the header
+ // plus all of the load commands.
+ size_t header_size = sizeof(mach_header_type) + header->sizeofcmds;
+
+ if (ReadTaskMemory(images.task_,
+ image_address,
+ header_size,
+ mach_header_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ // Read the file name from the task's memory space.
+ string file_path;
+ if (file_path_address) {
+ // Although we're reading kMaxStringLength bytes, it's copied in the
+ // the DynamicImage constructor below with the correct string length,
+ // so it's not really wasting memory.
+ file_path = ReadTaskString(images.task_, file_path_address);
+ }
+
+ // Create an object representing this image and add it to our list.
+ DynamicImage *new_image;
+ new_image = new DynamicImage(&mach_header_bytes[0],
+ header_size,
+ image_address,
+ file_path,
+ static_cast<uintptr_t>(file_mod_date),
+ images.task_,
+ images.cpu_type_,
+ cpusubtype,
+ shared_cache_slide,
+ is_dyld);
+
+ if (new_image->IsValid()) {
+ images.image_list_.push_back(DynamicImageRef(new_image));
+ } else {
+ delete new_image;
+ }
+}
+
+template<typename MachBits>
+void ReadImageInfo(DynamicImages& images,
+ uint64_t image_list_address) {
+ typedef typename MachBits::dyld_image_info dyld_image_info;
+ typedef typename MachBits::dyld_all_image_infos dyld_all_image_infos;
+
+ // Read the structure inside of dyld that contains information about
+ // loaded images. We're reading from the desired task's address space.
+
+ // Here we make the assumption that dyld loaded at the same address in
+ // the crashed process vs. this one. This is an assumption made in
+ // "dyld_debug.c" and is said to be nearly always valid.
+ vector<uint8_t> dyld_all_info_bytes;
+ if (ReadTaskMemory(images.task_,
+ image_list_address,
+ sizeof(dyld_all_image_infos),
+ dyld_all_info_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_all_image_infos *dyldInfo =
+ reinterpret_cast<dyld_all_image_infos*>(&dyld_all_info_bytes[0]);
+
+ // number of loaded images
+ int count = dyldInfo->infoArrayCount;
+
+ // Read an array of dyld_image_info structures each containing
+ // information about a loaded image.
+ vector<uint8_t> dyld_info_array_bytes;
+ if (ReadTaskMemory(images.task_,
+ dyldInfo->infoArray,
+ count * sizeof(dyld_image_info),
+ dyld_info_array_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_image_info *infoArray =
+ reinterpret_cast<dyld_image_info*>(&dyld_info_array_bytes[0]);
+ // Add room for dyld at the end
+ images.image_list_.reserve(count + 1);
+
+ for (int i = 0; i < count; ++i) {
+ dyld_image_info &info = infoArray[i];
+ ReadOneImageInfo<MachBits>(images, info.load_address_,
+ info.file_path_, info.file_mod_date_,
+ dyldInfo->sharedCacheSlide,
+ /* is_dyld */ false);
+ }
+
+ // Add an image for dyld itself. It doesn't appear in the standard list of
+ // modules.
+ uint64_t dyld_address = (uint64_t) dyldInfo->dyldImageLoadAddress;
+ if (dyld_address) {
+ ReadOneImageInfo<MachBits>(images, dyld_address,
+ (uint64_t) dyldInfo->dyldPath,
+ /* file_mod_date */ 0,
+ dyldInfo->sharedCacheSlide,
+ /* is_dyld */ true);
+ }
+
+ // sorts based on loading address
+ sort(images.image_list_.begin(), images.image_list_.end());
+ // remove duplicates - this happens in certain strange cases
+ // You can see it in DashboardClient when Google Gadgets plugin
+ // is installed. Apple's crash reporter log and gdb "info shared"
+ // both show the same library multiple times at the same address
+
+ vector<DynamicImageRef>::iterator it = unique(images.image_list_.begin(),
+ images.image_list_.end());
+ images.image_list_.erase(it, images.image_list_.end());
+}
+
+void DynamicImages::ReadImageInfoForTask() {
+ uint64_t imageList = GetDyldAllImageInfosPointer();
+
+ if (imageList) {
+ if (Is64Bit())
+ ReadImageInfo<MachO64>(*this, imageList);
+ else
+ ReadImageInfo<MachO32>(*this, imageList);
+ }
+}
+
+//==============================================================================
+DynamicImage *DynamicImages::GetExecutableImage() {
+ int executable_index = GetExecutableImageIndex();
+
+ if (executable_index >= 0) {
+ return GetImage(executable_index);
+ }
+
+ return NULL;
+}
+
+//==============================================================================
+// returns -1 if failure to find executable
+int DynamicImages::GetExecutableImageIndex() {
+ int image_count = GetImageCount();
+
+ for (int i = 0; i < image_count; ++i) {
+ DynamicImage *image = GetImage(i);
+ if (image->GetFileType() == MH_EXECUTE) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+//==============================================================================
+// static
+cpu_type_t DynamicImages::DetermineTaskCPUType(task_t task) {
+ if (task == mach_task_self())
+ return GetNativeCPUType();
+
+ int mib[CTL_MAXNAME];
+ size_t mibLen = CTL_MAXNAME;
+ int err = sysctlnametomib("sysctl.proc_cputype", mib, &mibLen);
+ if (err == 0) {
+ assert(mibLen < CTL_MAXNAME);
+ pid_for_task(task, &mib[mibLen]);
+ mibLen += 1;
+
+ cpu_type_t cpu_type;
+ size_t cpuTypeSize = sizeof(cpu_type);
+ sysctl(mib, static_cast<u_int>(mibLen), &cpu_type, &cpuTypeSize, 0, 0);
+ return cpu_type;
+ }
+
+ return GetNativeCPUType();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h
new file mode 100644
index 0000000000..e225c00b88
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h
@@ -0,0 +1,386 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// dynamic_images.h
+//
+// Implements most of the function of the dyld API, but allowing an
+// arbitrary task to be introspected, unlike the dyld API which
+// only allows operation on the current task. The current implementation
+// is limited to use by 32-bit tasks.
+
+#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+
+#include <mach/mach.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+#include "mach_vm_compat.h"
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+//==============================================================================
+// The memory layout of this struct matches the dyld_image_info struct
+// defined in "dyld_gdb.h" in the darwin source.
+typedef struct dyld_image_info32 {
+ uint32_t load_address_; // struct mach_header*
+ uint32_t file_path_; // char*
+ uint32_t file_mod_date_;
+} dyld_image_info32;
+
+typedef struct dyld_image_info64 {
+ uint64_t load_address_; // struct mach_header*
+ uint64_t file_path_; // char*
+ uint64_t file_mod_date_;
+} dyld_image_info64;
+
+//==============================================================================
+// This is as defined in "dyld_gdb.h" in the darwin source.
+// _dyld_all_image_infos (in dyld) is a structure of this type
+// which will be used to determine which dynamic code has been loaded.
+typedef struct dyld_all_image_infos32 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint32_t infoArray; // const struct dyld_image_info*
+ uint32_t notification;
+ bool processDetachedFromSharedRegion;
+ // Only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later
+ const struct mach_header* dyldImageLoadAddress;
+ uint32_t padding[14];
+ // Only in version 12 (Mac OS X 10.7, iOS 4.3) and later
+ uint32_t sharedCacheSlide;
+ uint32_t padding1[6];
+ // Only in version 15 (macOS 10.12, iOS 10.0) and later
+ const char* dyldPath;
+} dyld_all_image_infos32;
+
+typedef struct dyld_all_image_infos64 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint64_t infoArray; // const struct dyld_image_info*
+ uint64_t notification;
+ bool processDetachedFromSharedRegion;
+ // Only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later
+ const struct mach_header_64* dyldImageLoadAddress;
+ uint64_t padding[14];
+ // Only in version 12 (Mac OS X 10.7, iOS 4.3) and later
+ uint64_t sharedCacheSlide;
+ uint64_t padding1[4];
+ // Only in version 15 (macOS 10.12, iOS 10.0) and later
+ const char* dyldPath;
+} dyld_all_image_infos64;
+
+// some typedefs to isolate 64/32 bit differences
+#ifdef __LP64__
+typedef mach_header_64 breakpad_mach_header;
+typedef segment_command_64 breakpad_mach_segment_command;
+#else
+typedef mach_header breakpad_mach_header;
+typedef segment_command breakpad_mach_segment_command;
+#endif
+
+// Bit in mach_header.flags that indicates whether or not the image is in the
+// dyld shared cache. The dyld shared cache is a single image into which
+// commonly used system dylibs and frameworks are incorporated. dyld maps it
+// into every process at load time. The component images all have the same
+// slide.
+#define MH_SHAREDCACHE 0x80000000
+
+// Helper functions to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImage;
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image);
+
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+//==============================================================================
+// Represents a single dynamically loaded mach-o image
+class DynamicImage {
+ public:
+ DynamicImage(uint8_t *header, // data is copied
+ size_t header_size, // includes load commands
+ uint64_t load_address,
+ string file_path,
+ uintptr_t image_mod_date,
+ mach_port_t task,
+ cpu_type_t cpu_type,
+ cpu_subtype_t cpu_subtype,
+ ptrdiff_t shared_cache_slide,
+ bool is_dyld)
+ : header_(header, header + header_size),
+ header_size_(header_size),
+ load_address_(load_address),
+ vmaddr_(0),
+ vmsize_(0),
+ slide_(0),
+ crash_info_(),
+ version_(0),
+ file_path_(file_path),
+ file_mod_date_(image_mod_date),
+ is_dyld_(is_dyld),
+ task_(task),
+ cpu_type_(cpu_type),
+ cpu_subtype_(cpu_subtype),
+ shared_cache_slide_(shared_cache_slide) {
+ CalculateMemoryAndVersionInfo();
+ }
+
+ // Size of mach_header plus load commands
+ size_t GetHeaderSize() const {return header_.size();}
+
+ // Full path to mach-o binary
+ string GetFilePath() {return file_path_;}
+
+ uint64_t GetModDate() const {return file_mod_date_;}
+
+ // Actual address where the image was loaded
+ uint64_t GetLoadAddress() const {return load_address_;}
+
+ // Address where the image should be loaded
+ mach_vm_address_t GetVMAddr() const {return vmaddr_;}
+
+ bool GetInDyldSharedCache()
+ {return (shared_cache_slide_ && (slide_ == shared_cache_slide_));}
+
+ bool GetIsDyld() {return is_dyld_;}
+
+ // Difference between GetLoadAddress() and GetVMAddr()
+ ptrdiff_t GetVMAddrSlide() const {return slide_;}
+
+ // Size of the image
+ mach_vm_size_t GetVMSize() const {return vmsize_;}
+
+ // Returns the address of the locally cached __DATA,__crash_info section.
+ // The vector will be empty if the image doesn't have a __crash_info
+ // section. But even if the vector isn't empty, its contents may be "empty"
+ // of useful data (see definition of crashreporter_annotations_t in
+ // mach_vm_compat.h).
+ mach_vm_address_t GetCrashInfo() const {
+ return reinterpret_cast<mach_vm_address_t>(&crash_info_[0]);
+ }
+
+ // Size of the locally cached __DATA,__crash_info section. This will be zero
+ // if the vector is empty. But even if it's non-zero, the __crash_info
+ // section of which it's a copy may be empty of useful data.
+ size_t GetCrashInfoSize() const {return crash_info_.size();}
+
+ // Task owning this loaded image
+ mach_port_t GetTask() {return task_;}
+
+ // CPU type of the task and the image
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // CPU subtype of the image
+ cpu_type_t GetCPUSubtype() {return cpu_subtype_;}
+
+ // filetype from the Mach-O header.
+ uint32_t GetFileType();
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ uint32_t GetVersion() {return version_;}
+ // For sorting
+ bool operator<(const DynamicImage &inInfo) {
+ return GetLoadAddress() < inInfo.GetLoadAddress();
+ }
+
+ // Sanity checking
+ bool IsValid() {return GetVMSize() != 0;}
+
+ private:
+ DynamicImage(const DynamicImage &);
+ DynamicImage &operator=(const DynamicImage &);
+
+ friend class DynamicImages;
+ template<typename MachBits>
+ friend bool FindTextSection(DynamicImage& image);
+ template<typename MachBits>
+ friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+ // Initializes vmaddr_, vmsize_, and slide_
+ void CalculateMemoryAndVersionInfo();
+
+ const vector<uint8_t> header_; // our local copy of the header
+ size_t header_size_; // mach_header plus load commands
+ uint64_t load_address_; // base address image is mapped into
+ mach_vm_address_t vmaddr_;
+ mach_vm_size_t vmsize_;
+ ptrdiff_t slide_;
+ vector<uint8_t> crash_info_;
+ uint32_t version_; // Dylib version
+ string file_path_; // path dyld used to load the image
+ uintptr_t file_mod_date_; // time_t of image file
+ bool is_dyld_; // Is image file dyld itself?
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_ and image
+ cpu_subtype_t cpu_subtype_; // CPU subtype of image
+ ptrdiff_t shared_cache_slide_; // Task's shared cache slide
+};
+
+//==============================================================================
+// DynamicImageRef is just a simple wrapper for a pointer to
+// DynamicImage. The reason we use it instead of a simple typedef is so
+// that we can use stl::sort() on a vector of DynamicImageRefs
+// and simple class pointers can't implement operator<().
+//
+class DynamicImageRef {
+ public:
+ explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
+ // The copy constructor is required by STL
+ DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
+
+ bool operator<(const DynamicImageRef &inRef) const {
+ return (*const_cast<DynamicImageRef*>(this)->p)
+ < (*const_cast<DynamicImageRef&>(inRef).p);
+ }
+
+ bool operator==(const DynamicImageRef &inInfo) const {
+ return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
+ (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
+ }
+
+ // Be just like DynamicImage*
+ DynamicImage *operator->() {return p;}
+ operator DynamicImage*() {return p;}
+
+ private:
+ DynamicImage *p;
+};
+
+// Helper function to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImages;
+template<typename MachBits>
+void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld);
+template<typename MachBits>
+void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+//==============================================================================
+// An object of type DynamicImages may be created to allow introspection of
+// an arbitrary task's dynamically loaded mach-o binaries. This makes the
+// assumption that the current task has send rights to the target task.
+class DynamicImages {
+ public:
+ explicit DynamicImages(mach_port_t task);
+
+ ~DynamicImages() {
+ for (int i = 0; i < GetImageCount(); ++i) {
+ delete image_list_[i];
+ }
+ }
+
+ // Returns the number of dynamically loaded mach-o images.
+ int GetImageCount() const {return static_cast<int>(image_list_.size());}
+
+ // Returns an individual image.
+ DynamicImage *GetImage(int i) {
+ if (i < (int)image_list_.size()) {
+ return image_list_[i];
+ }
+ return NULL;
+ }
+
+ // Returns the image corresponding to the main executable.
+ DynamicImage *GetExecutableImage();
+ int GetExecutableImageIndex();
+
+ // Returns the task which we're looking at.
+ mach_port_t GetTask() const {return task_;}
+
+ // CPU type of the task
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ // Determine the CPU type of the task being dumped.
+ static cpu_type_t DetermineTaskCPUType(task_t task);
+
+ // Get the native CPU type of this task.
+ static cpu_type_t GetNativeCPUType() {
+#if defined(__i386__)
+ return CPU_TYPE_I386;
+#elif defined(__x86_64__)
+ return CPU_TYPE_X86_64;
+#elif defined(__ppc__)
+ return CPU_TYPE_POWERPC;
+#elif defined(__ppc64__)
+ return CPU_TYPE_POWERPC64;
+#elif defined(__arm__)
+ return CPU_TYPE_ARM;
+#elif defined(__aarch64__)
+ return CPU_TYPE_ARM64;
+#else
+#error "GetNativeCPUType not implemented for this architecture"
+#endif
+ }
+
+ private:
+ template<typename MachBits>
+ friend void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld);
+ template<typename MachBits>
+ friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+ bool IsOurTask() {return task_ == mach_task_self();}
+
+ // Initialization
+ void ReadImageInfoForTask();
+ uint64_t GetDyldAllImageInfosPointer();
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_
+ vector<DynamicImageRef> image_list_;
+};
+
+// Fill bytes with the contents of memory at a particular
+// location in another task.
+kern_return_t ReadTaskMemory(task_port_t target_task,
+ const uint64_t address,
+ size_t length,
+ vector<uint8_t> &bytes);
+
+std::string ReadTaskString(task_port_t target_task,
+ const uint64_t address);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
new file mode 100644
index 0000000000..c39d66ba41
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
@@ -0,0 +1,990 @@
+// 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 <mach/exc.h>
+#include <mach/mig.h>
+#include <pthread.h>
+#include <signal.h>
+#include <TargetConditionals.h>
+
+#include <map>
+
+#include "mac/handler/exception_handler.h"
+#include "mac/handler/minidump_generator.h"
+#include "common/mac/macho_utilities.h"
+#include "common/mac/scoped_task_suspend-inl.h"
+#include "google_breakpad/common/minidump_exception_mac.h"
+#include "mozilla/Assertions.h"
+
+#ifdef MOZ_PHC
+#include "replace_malloc_bridge.h"
+#endif
+
+#ifndef __EXCEPTIONS
+// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
+// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
+// exceptions disabled even when other C++ libraries are used. #undef the try
+// and catch macros first in case libstdc++ is in use and has already provided
+// its own definitions.
+#undef try
+#define try if (true)
+#undef catch
+#define catch(X) if (false)
+#endif // __EXCEPTIONS
+
+#ifndef USE_PROTECTED_ALLOCATIONS
+#if TARGET_OS_IPHONE
+#define USE_PROTECTED_ALLOCATIONS 1
+#else
+#define USE_PROTECTED_ALLOCATIONS 0
+#endif
+#endif
+
+// If USE_PROTECTED_ALLOCATIONS is activated then the
+// gBreakpadAllocator needs to be setup in other code
+// ahead of time. Please see ProtectedMemoryAllocator.h
+// for more details.
+#if USE_PROTECTED_ALLOCATIONS
+ #include "protected_memory_allocator.h"
+ extern ProtectedMemoryAllocator *gBreakpadAllocator;
+#endif
+
+namespace google_breakpad {
+
+static union {
+#if USE_PROTECTED_ALLOCATIONS
+#if defined PAGE_MAX_SIZE
+ char protected_buffer[PAGE_MAX_SIZE] __attribute__((aligned(PAGE_MAX_SIZE)));
+#else
+ char protected_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+#endif // defined PAGE_MAX_SIZE
+#endif // USE_PROTECTED_ALLOCATIONS
+ google_breakpad::ExceptionHandler *handler;
+} gProtectedData;
+
+using std::map;
+
+// These structures and techniques are illustrated in
+// Mac OS X Internals, Amit Singh, ch 9.7
+#pragma pack(push, 4)
+struct ExceptionMessage {
+ mach_msg_header_t header;
+ mach_msg_body_t body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ NDR_record_t ndr;
+ exception_type_t exception;
+ mach_msg_type_number_t code_count;
+ mach_exception_data_type_t code[EXCEPTION_CODE_MAX];
+ char padding[512];
+};
+#pragma pack(pop)
+
+struct ExceptionParameters {
+ ExceptionParameters() : count(0) {}
+ mach_msg_type_number_t count;
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ mach_port_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+};
+
+#pragma pack(push, 4)
+struct ExceptionReplyMessage {
+ mach_msg_header_t header;
+ NDR_record_t ndr;
+ kern_return_t return_code;
+};
+#pragma pack(pop)
+
+// Only catch these three exceptions. The other ones are nebulously defined
+// and may result in treating a non-fatal exception as fatal.
+exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS |
+EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT |
+EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD;
+
+kern_return_t ForwardException(mach_port_t task,
+ mach_port_t failed_thread,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count);
+
+// The contents of mach_exc_server() and mach_exception_raise() are derived
+// from /usr/include/mach/mach_exc.defs, as follows:
+//
+// 1) Run 'mig mach_exc.defs' which creates the following files:
+// mach_exc.h
+// mach_excServer.c
+// mach_excUser.c
+// 2) The relevant code for mach_exc_server() comes from the following methods
+// in mach_excServer.c:
+// mach_exc_server()
+// _Xmach_exception_raise()
+// 3) The relevant code for mach_exception_raise() comes from the following
+// method in mach_excUser.c:
+// mach_exception_raise()
+boolean_t mach_exc_server(mach_msg_header_t* InHeadP,
+ mach_msg_header_t* OutHeadP)
+{
+ OutHeadP->msgh_bits =
+ MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0);
+ OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port;
+ /* Minimal size: mach_exception_raise() will update it if different */
+ OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
+ OutHeadP->msgh_local_port = MACH_PORT_NULL;
+ OutHeadP->msgh_id = InHeadP->msgh_id + 100;
+ OutHeadP->msgh_reserved = 0;
+
+ if (InHeadP->msgh_id != 2405) {
+ ((mig_reply_error_t*)OutHeadP)->NDR = NDR_record;
+ ((mig_reply_error_t*)OutHeadP)->RetCode = MIG_BAD_ID;
+ return FALSE;
+ }
+
+#pragma pack(push, 4)
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ int64_t code[2];
+ mach_msg_trailer_t trailer;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ } Reply;
+#pragma pack(pop)
+
+ Request* In0P = (Request*)InHeadP;
+ Reply* OutP = (Reply*)OutHeadP;
+
+ if (In0P->task.name != mach_task_self()) {
+ // This exception was not meant for us, we avoid forwarding it (because it
+ // could cause a loop in the exception handler) and simply ignore it
+ // instead.
+ return TRUE;
+ }
+
+ OutP->RetCode = ForwardException(In0P->task.name,
+ In0P->thread.name,
+ In0P->exception,
+ In0P->code,
+ In0P->codeCnt);
+ OutP->NDR = NDR_record;
+ return TRUE;
+}
+
+kern_return_t mach_exception_raise(mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t codeCnt)
+{
+#pragma pack(push, 4)
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ int64_t code[2];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ mach_msg_trailer_t trailer;
+ } Reply;
+#pragma pack(pop)
+
+ Request In;
+ Request *InP = &In;
+
+ mach_msg_return_t msg_result;
+ unsigned int msgh_size;
+
+ InP->msgh_body.msgh_descriptor_count = 2;
+ InP->thread.name = thread;
+ InP->thread.disposition = 19;
+ InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
+ InP->task.name = task;
+ InP->task.disposition = 19;
+ InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
+
+ InP->NDR = NDR_record;
+
+ InP->exception = exception;
+
+ if (codeCnt > 2) {
+ { return MIG_ARRAY_TOO_LARGE; }
+ }
+ (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
+
+ InP->codeCnt = codeCnt;
+
+ msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt));
+ InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX |
+ MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_remote_port = exception_port;
+ InP->Head.msgh_local_port = mig_get_reply_port();
+ InP->Head.msgh_id = 2405;
+ InP->Head.msgh_reserved = 0;
+
+ msg_result = mach_msg(&InP->Head,
+ MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE,
+ msgh_size,
+ (mach_msg_size_t)sizeof(Reply),
+ InP->Head.msgh_local_port,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+
+ if (msg_result != MACH_MSG_SUCCESS) {
+ fprintf(stderr, "** mach_msg() error forwarding exception!!\n");
+ return msg_result;
+ }
+
+ return KERN_SUCCESS;
+}
+
+ExceptionHandler::ExceptionHandler(const string &dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ bool install_handler,
+ const char* port_name)
+ : dump_path_(),
+ filter_(filter),
+ callback_(callback),
+ callback_context_(callback_context),
+ directCallback_(NULL),
+ handler_thread_(NULL),
+ handler_port_(MACH_PORT_NULL),
+ previous_(NULL),
+ installed_exception_handler_(false),
+ is_in_teardown_(false),
+ last_minidump_write_result_(false),
+ use_minidump_write_mutex_(false) {
+ // This will update to the ID and C-string pointers
+ set_dump_path(dump_path);
+ MinidumpGenerator::GatherSystemInformation();
+#if !TARGET_OS_IPHONE
+ if (port_name)
+ crash_generation_client_.reset(new CrashGenerationClient(port_name));
+#endif
+ Setup(install_handler);
+}
+
+// special constructor if we want to bypass minidump writing and
+// simply get a callback with the exception information
+ExceptionHandler::ExceptionHandler(DirectCallback callback,
+ void* callback_context,
+ bool install_handler)
+ : dump_path_(),
+ filter_(NULL),
+ callback_(NULL),
+ callback_context_(callback_context),
+ directCallback_(callback),
+ handler_thread_(NULL),
+ handler_port_(MACH_PORT_NULL),
+ previous_(NULL),
+ installed_exception_handler_(false),
+ is_in_teardown_(false),
+ last_minidump_write_result_(false),
+ use_minidump_write_mutex_(false) {
+ MinidumpGenerator::GatherSystemInformation();
+ Setup(install_handler);
+}
+
+ExceptionHandler::~ExceptionHandler() {
+ Teardown();
+}
+
+bool ExceptionHandler::WriteMinidump(bool write_exception_stream) {
+ // If we're currently writing, just return
+ if (use_minidump_write_mutex_)
+ return false;
+
+ use_minidump_write_mutex_ = true;
+ last_minidump_write_result_ = false;
+
+ // Lock the mutex. Since we just created it, this will return immediately.
+ if (pthread_mutex_lock(&minidump_write_mutex_) == 0) {
+ // Send an empty message to the handle port so that a minidump will
+ // be written
+ bool result = SendMessageToHandlerThread(write_exception_stream ?
+ kWriteDumpWithExceptionMessage :
+ kWriteDumpMessage);
+ if (!result) {
+ pthread_mutex_unlock(&minidump_write_mutex_);
+ return false;
+ }
+
+ // Wait for the minidump writer to complete its writing. It will unlock
+ // the mutex when completed
+ pthread_mutex_lock(&minidump_write_mutex_);
+ }
+
+ use_minidump_write_mutex_ = false;
+ UpdateNextID();
+ return last_minidump_write_result_;
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const string &dump_path,
+ bool write_exception_stream,
+ MinidumpCallback callback,
+ void* callback_context) {
+ ExceptionHandler handler(dump_path, NULL, callback, callback_context, false,
+ NULL);
+ return handler.WriteMinidump(write_exception_stream);
+}
+
+// static
+bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
+ mach_port_t child_blamed_thread,
+ const string &dump_path,
+ MinidumpCallback callback,
+ void* callback_context) {
+ ScopedTaskSuspend suspend(child);
+
+ MinidumpGenerator generator(child, MACH_PORT_NULL);
+ string dump_id;
+ string dump_filename = generator.UniqueNameInDirectory(dump_path, &dump_id);
+
+ generator.SetExceptionInformation(EXC_BREAKPOINT,
+#if defined(__i386__) || defined(__x86_64__)
+ EXC_I386_BPT,
+#elif defined(__ppc__) || defined(__ppc64__)
+ EXC_PPC_BREAKPOINT,
+#elif defined(__arm__) || defined(__aarch64__)
+ EXC_ARM_BREAKPOINT,
+#else
+#error architecture not supported
+#endif
+ 0,
+ child_blamed_thread);
+ bool result = generator.Write(dump_filename.c_str());
+
+ if (callback) {
+ return callback(dump_path.c_str(), dump_id.c_str(),
+ callback_context, nullptr, result);
+ }
+ return result;
+}
+
+#ifdef MOZ_PHC
+static void GetPHCAddrInfo(int exception_type, int64_t exception_subcode,
+ mozilla::phc::AddrInfo* addr_info) {
+ // Is this a crash involving a PHC allocation?
+ if (exception_type == EXC_BAD_ACCESS) {
+ // `exception_subcode` is only non-zero when it's a bad access, in which
+ // case it holds the address of the bad access.
+ char* addr = reinterpret_cast<char*>(exception_subcode);
+ ReplaceMalloc::IsPHCAllocation(addr, addr_info);
+ }
+}
+#endif
+
+bool ExceptionHandler::WriteMinidumpWithException(
+ int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ breakpad_ucontext_t* task_context,
+ mach_port_t thread_name,
+ mach_port_t task_name,
+ bool exit_after_write,
+ bool report_current_thread) {
+ bool result = false;
+
+#if TARGET_OS_IPHONE
+ // _exit() should never be called on iOS.
+ exit_after_write = false;
+#endif
+
+ mozilla::phc::AddrInfo addr_info;
+#ifdef MOZ_PHC
+ GetPHCAddrInfo(exception_type, exception_subcode, &addr_info);
+#endif
+
+ if (directCallback_) {
+ if (directCallback_(callback_context_,
+ exception_type,
+ exception_code,
+ exception_subcode,
+ thread_name) ) {
+ if (exit_after_write)
+ _exit(exception_type);
+ }
+#if !TARGET_OS_IPHONE
+ } else if (IsOutOfProcess()) {
+ if (exception_type && exception_code) {
+ // If this is a real exception, give the filter (if any) a chance to
+ // decide if this should be sent.
+ if (filter_ && !filter_(callback_context_))
+ return false;
+ result = crash_generation_client_->RequestDumpForException(
+ exception_type,
+ exception_code,
+ exception_subcode,
+ thread_name,
+ task_name);
+
+ if (callback_) {
+ result = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+ &addr_info, result);
+ }
+
+ if (result && exit_after_write) {
+ _exit(exception_type);
+ }
+ }
+#endif
+ } else {
+ string minidump_id;
+
+ // Putting the MinidumpGenerator in its own context will ensure that the
+ // destructor is executed, closing the newly created minidump file.
+ if (!dump_path_.empty()) {
+ MinidumpGenerator md(mach_task_self(),
+ report_current_thread ? MACH_PORT_NULL :
+ mach_thread_self());
+ md.SetTaskContext(task_context);
+ if (exception_type && exception_code) {
+ // If this is a real exception, give the filter (if any) a chance to
+ // decide if this should be sent.
+ if (filter_ && !filter_(callback_context_))
+ return false;
+
+ md.SetExceptionInformation(exception_type, exception_code,
+ exception_subcode, thread_name);
+ }
+
+ result = md.Write(next_minidump_path_c_);
+ }
+
+ // Call user specified callback (if any)
+ if (callback_) {
+ result = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+ &addr_info, result);
+ // If the user callback returned true and we're handling an exception
+ // (rather than just writing out the file), then we should exit without
+ // forwarding the exception to the next handler.
+ if (result) {
+ if (exit_after_write)
+ _exit(exception_type);
+ }
+ }
+ }
+
+ return result;
+}
+
+kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count) {
+ // At this time, we should have called Uninstall() on the exception handler
+ // so that the current exception ports are the ones that we should be
+ // forwarding to.
+ ExceptionParameters current;
+
+ current.count = EXC_TYPES_COUNT;
+ mach_port_t current_task = mach_task_self();
+ task_get_exception_ports(current_task,
+ s_exception_mask,
+ current.masks,
+ &current.count,
+ current.ports,
+ current.behaviors,
+ current.flavors);
+
+ // Find the first exception handler that matches the exception
+ unsigned int found;
+ for (found = 0; found < current.count; ++found) {
+ if (current.masks[found] & (1 << exception)) {
+ break;
+ }
+ }
+
+ // Nothing to forward
+ if (found == current.count) {
+ fprintf(stderr, "** No previous ports for forwarding!! \n");
+ _exit(KERN_FAILURE);
+ }
+
+ mach_port_t target_port = current.ports[found];
+ exception_behavior_t target_behavior = current.behaviors[found];
+
+ kern_return_t result;
+ switch (target_behavior & ~MACH_EXCEPTION_CODES) {
+ case EXCEPTION_DEFAULT:
+ result = mach_exception_raise(target_port, failed_thread, task, exception,
+ code, code_count);
+ break;
+ default:
+ fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
+ result = KERN_FAILURE;
+ break;
+ }
+
+ return result;
+}
+
+// static
+void* ExceptionHandler::WaitForMessage(void* exception_handler_class) {
+ pthread_setname_np("Breakpad ExceptionHandler");
+
+ ExceptionHandler* self =
+ reinterpret_cast<ExceptionHandler*>(exception_handler_class);
+ ExceptionMessage receive;
+
+ // Wait for the exception info
+ while (1) {
+ receive.header.msgh_local_port = self->handler_port_;
+ receive.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(receive));
+ kern_return_t result = mach_msg(&(receive.header),
+ MACH_RCV_MSG | MACH_RCV_LARGE, 0,
+ receive.header.msgh_size,
+ self->handler_port_,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+
+ if (result == KERN_SUCCESS) {
+ // Uninstall our handler so that we don't get in a loop if the process of
+ // writing out a minidump causes an exception. However, if the exception
+ // was caused by a fork'd process, don't uninstall things
+
+ // If the actual exception code is zero, then we're calling this handler
+ // in a way that indicates that we want to either exit this thread or
+ // generate a minidump
+ //
+ // While reporting, all threads (except this one) must be suspended
+ // to avoid misleading stacks. If appropriate they will be resumed
+ // afterwards.
+ if (!receive.exception) {
+ // Don't touch self, since this message could have been sent
+ // from its destructor.
+ if (receive.header.msgh_id == kShutdownMessage)
+ return NULL;
+
+ self->SuspendThreads();
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ mach_port_t thread = MACH_PORT_NULL;
+ int exception_type = 0;
+ int64_t exception_code = 0;
+ if (receive.header.msgh_id == kWriteDumpWithExceptionMessage) {
+ thread = receive.thread.name;
+ exception_type = EXC_BREAKPOINT;
+#if defined(__i386__) || defined(__x86_64__)
+ exception_code = EXC_I386_BPT;
+#elif defined(__ppc__) || defined(__ppc64__)
+ exception_code = EXC_PPC_BREAKPOINT;
+#elif defined(__arm__) || defined(__aarch64__)
+ exception_code = EXC_ARM_BREAKPOINT;
+#else
+#error architecture not supported
+#endif
+ }
+
+ // Write out the dump and save the result for later retrieval
+ self->last_minidump_write_result_ =
+ self->WriteMinidumpWithException(exception_type, exception_code,
+ 0, NULL, thread, mach_task_self(),
+ false, false);
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+
+ self->ResumeThreads();
+
+ if (self->use_minidump_write_mutex_)
+ pthread_mutex_unlock(&self->minidump_write_mutex_);
+ } else {
+ bool crash_reported = false;
+
+ // When forking a child process with the exception handler installed,
+ // if the child crashes, it will send the exception back to the parent
+ // process. The check for task == self_task() ensures that only
+ // exceptions that occur in the parent process are caught and
+ // processed.
+ if (receive.task.name == mach_task_self()) {
+ self->SuspendThreads();
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ mach_exception_data_type_t subcode = 0;
+ if (receive.code_count > 1) {
+ switch (receive.exception) {
+ case EXC_BAD_ACCESS:
+ case EXC_CRASH:
+ case EXC_RESOURCE:
+ case EXC_GUARD:
+ subcode = receive.code[1];
+ break;
+ default:
+ subcode = 0;
+ }
+ }
+
+ // Generate the minidump with the exception data.
+ crash_reported =
+ self->WriteMinidumpWithException(receive.exception, receive.code[0],
+ subcode, NULL, receive.thread.name,
+ mach_task_self(), true, false);
+
+#if USE_PROTECTED_ALLOCATIONS
+ // This may have become protected again within
+ // WriteMinidumpWithException, but it needs to be unprotected for
+ // UninstallHandler.
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ self->UninstallHandler(true);
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+ }
+
+ ExceptionReplyMessage reply;
+ if (!mach_exc_server(&receive.header, &reply.header)) {
+ MOZ_CRASH_UNSAFE_PRINTF("Mach message id: %d crash reported = %d",
+ receive.header.msgh_id, crash_reported);
+ }
+
+ // Send a reply and exit
+ mach_msg(&(reply.header), MACH_SEND_MSG,
+ reply.header.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// static
+void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+ gProtectedData.handler->WriteMinidumpWithException(
+ EXC_SOFTWARE,
+ MD_EXCEPTION_CODE_MAC_ABORT,
+ 0,
+ static_cast<breakpad_ucontext_t*>(uc),
+ mach_thread_self(),
+ mach_task_self(),
+ true,
+ true);
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+}
+
+// static
+bool ExceptionHandler::WriteForwardedExceptionMinidump(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread,
+ mach_port_t task)
+{
+ if (!gProtectedData.handler) {
+ return false;
+ }
+ return gProtectedData.handler->WriteMinidumpWithException(exception_type, exception_code,
+ exception_subcode, NULL, thread, task,
+ /* exit_after_write = */ false,
+ /* report_current_thread = */ true);
+}
+
+bool ExceptionHandler::InstallHandler() {
+ // If a handler is already installed, something is really wrong.
+ if (gProtectedData.handler != NULL) {
+ return false;
+ }
+
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGABRT);
+ sa.sa_sigaction = ExceptionHandler::SignalHandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ scoped_ptr<struct sigaction> old(new struct sigaction);
+ if (sigaction(SIGABRT, &sa, old.get()) == -1) {
+ return false;
+ }
+ old_handler_.swap(old);
+ gProtectedData.handler = this;
+#if USE_PROTECTED_ALLOCATIONS
+ assert(((size_t)(gProtectedData.protected_buffer) & PAGE_MASK) == 0);
+ mprotect(gProtectedData.protected_buffer, PAGE_SIZE, PROT_READ);
+#endif
+
+ try {
+#if USE_PROTECTED_ALLOCATIONS
+ previous_ = new (gBreakpadAllocator->Allocate(sizeof(ExceptionParameters)) )
+ ExceptionParameters();
+#else
+ previous_ = new ExceptionParameters();
+#endif
+ }
+ catch (std::bad_alloc) {
+ return false;
+ }
+
+ // Save the current exception ports so that we can forward to them
+ previous_->count = EXC_TYPES_COUNT;
+ mach_port_t current_task = mach_task_self();
+ kern_return_t result = task_get_exception_ports(current_task,
+ s_exception_mask,
+ previous_->masks,
+ &previous_->count,
+ previous_->ports,
+ previous_->behaviors,
+ previous_->flavors);
+
+ // Setup the exception ports on this task. Such documentation as exists for
+ // task_set_exception_port() and friends can be found in the source code for
+ // xnu. Apple's implementation is available at https://opensource.apple.com/.
+ if (result == KERN_SUCCESS)
+ result = task_set_exception_ports(current_task, s_exception_mask,
+ handler_port_,
+ EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
+ THREAD_STATE_NONE);
+
+ installed_exception_handler_ = (result == KERN_SUCCESS);
+
+ return installed_exception_handler_;
+}
+
+bool ExceptionHandler::UninstallHandler(bool in_exception) {
+ kern_return_t result = KERN_SUCCESS;
+
+ if (old_handler_.get()) {
+ sigaction(SIGABRT, old_handler_.get(), NULL);
+#if USE_PROTECTED_ALLOCATIONS
+ mprotect(gProtectedData.protected_buffer, PAGE_SIZE,
+ PROT_READ | PROT_WRITE);
+#endif
+ // If we're handling an exception, leak the sigaction struct
+ // because it is unsafe to delete objects while in exception
+ // handling context.
+ if (in_exception) {
+ old_handler_.release();
+ } else {
+ old_handler_.reset();
+ }
+ gProtectedData.handler = NULL;
+ }
+
+ if (installed_exception_handler_) {
+ mach_port_t current_task = mach_task_self();
+
+ // Restore the previous ports
+ for (unsigned int i = 0; i < previous_->count; ++i) {
+ result = task_set_exception_ports(current_task, previous_->masks[i],
+ previous_->ports[i],
+ previous_->behaviors[i],
+ previous_->flavors[i]);
+ if (result != KERN_SUCCESS)
+ return false;
+ }
+
+ // this delete should NOT happen if an exception just occurred!
+ if (!in_exception) {
+#if USE_PROTECTED_ALLOCATIONS
+ previous_->~ExceptionParameters();
+#else
+ delete previous_;
+#endif
+ }
+
+ previous_ = NULL;
+ installed_exception_handler_ = false;
+ }
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::Setup(bool install_handler) {
+ if (pthread_mutex_init(&minidump_write_mutex_, NULL))
+ return false;
+
+ // Create a receive right
+ mach_port_t current_task = mach_task_self();
+ kern_return_t result = mach_port_allocate(current_task,
+ MACH_PORT_RIGHT_RECEIVE,
+ &handler_port_);
+ // Add send right
+ if (result == KERN_SUCCESS)
+ result = mach_port_insert_right(current_task, handler_port_, handler_port_,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ if (install_handler && result == KERN_SUCCESS)
+ if (!InstallHandler())
+ return false;
+
+ if (result == KERN_SUCCESS) {
+ // Install the handler in its own thread, detached as we won't be joining.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ int thread_create_result = pthread_create(&handler_thread_, &attr,
+ &WaitForMessage, this);
+ pthread_attr_destroy(&attr);
+ result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS;
+ }
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::Teardown() {
+ kern_return_t result = KERN_SUCCESS;
+ is_in_teardown_ = true;
+
+ if (!UninstallHandler(false))
+ return false;
+
+ // Send an empty message so that the handler_thread exits
+ if (SendMessageToHandlerThread(kShutdownMessage)) {
+ mach_port_t current_task = mach_task_self();
+ result = mach_port_deallocate(current_task, handler_port_);
+ if (result != KERN_SUCCESS)
+ return false;
+ } else {
+ return false;
+ }
+
+ handler_thread_ = NULL;
+ handler_port_ = MACH_PORT_NULL;
+ pthread_mutex_destroy(&minidump_write_mutex_);
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::SendMessageToHandlerThread(
+ HandlerThreadMessage message_id) {
+ ExceptionMessage msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.header.msgh_id = message_id;
+ if (message_id == kWriteDumpMessage ||
+ message_id == kWriteDumpWithExceptionMessage) {
+ // Include this thread's port.
+ msg.thread.name = mach_thread_self();
+ msg.thread.disposition = MACH_MSG_TYPE_PORT_SEND;
+ msg.thread.type = MACH_MSG_PORT_DESCRIPTOR;
+ }
+ msg.header.msgh_size = sizeof(msg) - sizeof(msg.padding);
+ msg.header.msgh_remote_port = handler_port_;
+ msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ kern_return_t result = mach_msg(&(msg.header),
+ MACH_SEND_MSG | MACH_SEND_TIMEOUT,
+ msg.header.msgh_size, 0, 0,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ return result == KERN_SUCCESS;
+}
+
+void ExceptionHandler::UpdateNextID() {
+ next_minidump_path_ =
+ (MinidumpGenerator::UniqueNameInDirectory(dump_path_, &next_minidump_id_));
+
+ next_minidump_path_c_ = next_minidump_path_.c_str();
+ next_minidump_id_c_ = next_minidump_id_.c_str();
+}
+
+bool ExceptionHandler::SuspendThreads() {
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+ return false;
+
+ // suspend all of the threads except for this one
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ if (threads_for_task[i] != mach_thread_self()) {
+ if (thread_suspend(threads_for_task[i]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ExceptionHandler::ResumeThreads() {
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+ return false;
+
+ // resume all of the threads except for this one
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ if (threads_for_task[i] != mach_thread_self()) {
+ if (thread_resume(threads_for_task[i]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
new file mode 100644
index 0000000000..24728a8c7c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
@@ -0,0 +1,297 @@
+// 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.
+
+// exception_handler.h: MacOS exception handler
+// This class can install a Mach exception port handler to trap most common
+// programming errors. If an exception occurs, a minidump file will be
+// generated which contains detailed information about the process and the
+// exception.
+
+#ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+#define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+
+#include <mach/mach.h>
+#include <TargetConditionals.h>
+
+#include <string>
+
+#include "mac/handler/ucontext_compat.h"
+#include "common/scoped_ptr.h"
+
+#if !TARGET_OS_IPHONE
+#include "mac/crash_generation/crash_generation_client.h"
+#endif
+
+#ifdef MOZ_PHC
+#include "PHC.h"
+#else
+namespace mozilla { namespace phc { class AddrInfo {}; } }
+#endif
+
+namespace google_breakpad {
+
+using std::string;
+
+struct ExceptionParameters;
+
+enum HandlerThreadMessage {
+ // Message ID telling the handler thread to write a dump.
+ kWriteDumpMessage = 0,
+ // Message ID telling the handler thread to write a dump and include
+ // an exception stream.
+ kWriteDumpWithExceptionMessage = 1,
+ // Message ID telling the handler thread to quit.
+ kShutdownMessage = 2
+};
+
+class ExceptionHandler {
+ public:
+ // A callback function to run before Breakpad performs any substantial
+ // processing of an exception. A FilterCallback is called before writing
+ // a minidump. context is the parameter supplied by the user as
+ // callback_context when the handler was created.
+ //
+ // If a FilterCallback returns true, Breakpad will continue processing,
+ // attempting to write a minidump. If a FilterCallback returns false, Breakpad
+ // will immediately report the exception as unhandled without writing a
+ // minidump, allowing another handler the opportunity to handle it.
+ typedef bool (*FilterCallback)(void *context);
+
+ // A callback function to run after the minidump has been written.
+ // |minidump_id| is a unique id for the dump, so the minidump
+ // file is <dump_dir>/<minidump_id>.dmp.
+ // |context| is the value passed into the constructor.
+ // |succeeded| indicates whether a minidump file was successfully written.
+ // Return true if the exception was fully handled and breakpad should exit.
+ // Return false to allow any other exception handlers to process the
+ // exception.
+ typedef bool (*MinidumpCallback)(const char *dump_dir,
+ const char *minidump_id,
+ void *context,
+ const mozilla::phc::AddrInfo* addr_info,
+ bool succeeded);
+
+ // A callback function which will be called directly if an exception occurs.
+ // This bypasses the minidump file writing and simply gives the client
+ // the exception information.
+ typedef bool (*DirectCallback)( void *context,
+ int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread_name);
+
+ // Creates a new ExceptionHandler instance to handle writing minidumps.
+ // Minidump files will be written to dump_path, and the optional callback
+ // is called after writing the dump file, as described above.
+ // If install_handler is true, then a minidump will be written whenever
+ // an unhandled exception occurs. If it is false, minidumps will only
+ // be written when WriteMinidump is called.
+ // If port_name is non-NULL, attempt to perform out-of-process dump generation
+ // If port_name is NULL, in-process dump generation will be used.
+ ExceptionHandler(const string &dump_path,
+ FilterCallback filter, MinidumpCallback callback,
+ void *callback_context, bool install_handler,
+ const char *port_name);
+
+ // A special constructor if we want to bypass minidump writing and
+ // simply get a callback with the exception information.
+ ExceptionHandler(DirectCallback callback,
+ void *callback_context,
+ bool install_handler);
+
+ ~ExceptionHandler();
+
+ // Get and set the minidump path.
+ string dump_path() const { return dump_path_; }
+ void set_dump_path(const string &dump_path) {
+ dump_path_ = dump_path;
+ dump_path_c_ = dump_path_.c_str();
+ UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_.
+ }
+
+ // Writes a minidump immediately. This can be used to capture the
+ // execution state independently of a crash. Returns true on success.
+ bool WriteMinidump() {
+ return WriteMinidump(false);
+ }
+
+ bool WriteMinidump(bool write_exception_stream);
+
+ // Convenience form of WriteMinidump which does not require an
+ // ExceptionHandler instance.
+ static bool WriteMinidump(const string &dump_path, MinidumpCallback callback,
+ void *callback_context) {
+ return WriteMinidump(dump_path, false, callback, callback_context);
+ }
+
+ static bool WriteMinidump(const string &dump_path,
+ bool write_exception_stream,
+ MinidumpCallback callback,
+ void *callback_context);
+
+ // Write a minidump of child immediately. This can be used to capture
+ // the execution state of a child process independently of a crash.
+ static bool WriteMinidumpForChild(mach_port_t child,
+ mach_port_t child_blamed_thread,
+ const std::string &dump_path,
+ MinidumpCallback callback,
+ void *callback_context);
+
+ // Write a minidump for an exception that was received by another handler.
+ static bool WriteForwardedExceptionMinidump(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread,
+ mach_port_t task);
+
+ // Returns whether out-of-process dump generation is used or not.
+ bool IsOutOfProcess() const {
+#if TARGET_OS_IPHONE
+ return false;
+#else
+ return crash_generation_client_.get() != NULL;
+#endif
+ }
+
+ private:
+ // Install the mach exception handler
+ bool InstallHandler();
+
+ // Uninstall the mach exception handler (if any)
+ bool UninstallHandler(bool in_exception);
+
+ // Setup the handler thread, and if |install_handler| is true, install the
+ // mach exception port handler
+ bool Setup(bool install_handler);
+
+ // Uninstall the mach exception handler (if any) and terminate the helper
+ // thread
+ bool Teardown();
+
+ // Send a mach message to the exception handler. Return true on
+ // success, false otherwise.
+ bool SendMessageToHandlerThread(HandlerThreadMessage message_id);
+
+ // All minidump writing goes through this one routine.
+ // |task_context| can be NULL. If not, it will be used to retrieve the
+ // context of the current thread, instead of using |thread_get_state|.
+ bool WriteMinidumpWithException(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ breakpad_ucontext_t *task_context,
+ mach_port_t thread_name,
+ mach_port_t task_name,
+ bool exit_after_write,
+ bool report_current_thread);
+
+ // When installed, this static function will be call from a newly created
+ // pthread with |this| as the argument
+ static void *WaitForMessage(void *exception_handler_class);
+
+ // Signal handler for SIGABRT.
+ static void SignalHandler(int sig, siginfo_t* info, void* uc);
+
+ // disallow copy ctor and operator=
+ explicit ExceptionHandler(const ExceptionHandler &);
+ void operator=(const ExceptionHandler &);
+
+ // Generates a new ID and stores it in next_minidump_id_, and stores the
+ // path of the next minidump to be written in next_minidump_path_.
+ void UpdateNextID();
+
+ // These functions will suspend/resume all threads except for the
+ // reporting thread
+ bool SuspendThreads();
+ bool ResumeThreads();
+
+ // The destination directory for the minidump
+ string dump_path_;
+
+ // The basename of the next minidump w/o extension
+ string next_minidump_id_;
+
+ // The full path to the next minidump to be written, including extension
+ string next_minidump_path_;
+
+ // Pointers to the UTF-8 versions of above
+ const char *dump_path_c_;
+ const char *next_minidump_id_c_;
+ const char *next_minidump_path_c_;
+
+ // The callback function and pointer to be passed back after the minidump
+ // has been written
+ FilterCallback filter_;
+ MinidumpCallback callback_;
+ void *callback_context_;
+
+ // The callback function to be passed back when we don't want a minidump
+ // file to be written
+ DirectCallback directCallback_;
+
+ // The thread that is created for the handler
+ pthread_t handler_thread_;
+
+ // The port that is waiting on an exception message to be sent, if the
+ // handler is installed
+ mach_port_t handler_port_;
+
+ // These variables save the previous exception handler's data so that it
+ // can be re-installed when this handler is uninstalled
+ ExceptionParameters *previous_;
+
+ // True, if we've installed the exception handler
+ bool installed_exception_handler_;
+
+ // True, if we're in the process of uninstalling the exception handler and
+ // the thread.
+ bool is_in_teardown_;
+
+ // Save the last result of the last minidump
+ bool last_minidump_write_result_;
+
+ // A mutex for use when writing out a minidump that was requested on a
+ // thread other than the exception handler.
+ pthread_mutex_t minidump_write_mutex_;
+
+ // True, if we're using the mutext to indicate when mindump writing occurs
+ bool use_minidump_write_mutex_;
+
+ // Old signal handler for SIGABRT. Used to be able to restore it when
+ // uninstalling.
+ scoped_ptr<struct sigaction> old_handler_;
+
+#if !TARGET_OS_IPHONE
+ // Client for out-of-process dump generation.
+ scoped_ptr<CrashGenerationClient> crash_generation_client_;
+#endif
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h b/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h
new file mode 100644
index 0000000000..aef3ad82f5
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
+#define CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
+
+#include <TargetConditionals.h>
+
+// On iOS 5 and higher, mach/mach_vm.h is not supported. Use the corresponding
+// vm_map functions instead.
+#if TARGET_OS_IPHONE
+#include <mach/vm_map.h>
+#define mach_vm_address_t vm_address_t
+#define mach_vm_deallocate vm_deallocate
+#define mach_vm_read vm_read
+#define mach_vm_region_recurse vm_region_recurse_64
+#define mach_vm_size_t vm_size_t
+#else
+#include <mach/mach_vm.h>
+#endif // TARGET_OS_IPHONE
+
+// This is the current (as of macOS 11.2.3) raw format of the data in the
+// __crash_info section of the __DATA segment. It must be read from memory
+// (__crash_info sections in file system modules are always empty of useful
+// data). The data (and that of its strings) may be readable from an out-of-
+// process image, but generally only if the module is in the dyld shared
+// cache. A __crash_info section is considered "empty of useful data" if all
+// of its fields besides 'version' are zero. The __crash_info section is only
+// present on macOS. Apple may add new fields to this structure in the future,
+// as they added 'abort_cause' when 'version' changed from '4' to '5'.
+// Breakpad should take this into account, and provide a way for new fields to
+// be added to future versions of MDRawMacCrashInfoRecord without breaking
+// older code.
+typedef struct { // Non-raw format
+ uint64_t version; // unsigned long
+ uint64_t message; // char *
+ uint64_t signature_string; // char *
+ uint64_t backtrace; // char *
+ uint64_t message2; // char *
+ // We can't use uint64_t for 'thread' in non-raw structures: Though uint64_t
+ // is the same size on all platforms, it's "unsigned long" on some platforms
+ // (like Android and Linux) and "unsigned long long" on others (like macOS
+ // and Windows).
+ uint64_t thread; // uint64_t, but we use unsigned long long
+ uint64_t dialog_mode; // unsigned int
+ // There's a string in the OSAnalytics private framework ("Abort Cause %lld")
+ // which hints that this field's non-raw format is long long.
+ uint64_t abort_cause; // long long, only present when
+ // 'version' > 4
+} crashreporter_annotations_t;
+
+// Defines for calls to getsectdatafromheader_64() or getsectdatafromheader().
+// __LP64__ is true on both amd64 and arm64 (Apple Silicon) hardware.
+#ifdef __LP64__
+ #define getsectdatafromheader_func getsectdatafromheader_64
+ typedef uint64_t getsectdata_size_type;
+#else
+ #define getsectdatafromheader_func getsectdatafromheader
+ typedef uint32_t getsectdata_size_type;
+#endif
+
+#endif // CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
new file mode 100644
index 0000000000..e13e4509b0
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
@@ -0,0 +1,2135 @@
+// 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 <algorithm>
+#include <cstdio>
+
+#include <mach/host_info.h>
+#include <mach/machine.h>
+#include <mach/vm_statistics.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <mach-o/getsect.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "mac/handler/minidump_generator.h"
+
+#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
+#include <mach/arm/thread_status.h>
+#endif
+#ifdef HAS_PPC_SUPPORT
+#include <mach/ppc/thread_status.h>
+#endif
+#ifdef HAS_X86_SUPPORT
+#include <mach/i386/thread_status.h>
+#endif
+
+#include "minidump_file_writer-inl.h"
+#include "common/mac/file_id.h"
+#include "common/mac/macho_id.h"
+#include "common/mac/string_utilities.h"
+
+using MacStringUtils::ConvertToString;
+using MacStringUtils::IntegerValueAtIndex;
+
+namespace google_breakpad {
+
+#if defined(__LP64__) && __LP64__
+#define LC_SEGMENT_ARCH LC_SEGMENT_64
+#define MH_MAGIC_ARCH MH_MAGIC_64
+#else
+#define LC_SEGMENT_ARCH LC_SEGMENT
+#define MH_MAGIC_ARCH MH_MAGIC
+#endif
+
+// constructor when generating from within the crashed process
+MinidumpGenerator::MinidumpGenerator()
+ : writer_(),
+ exception_type_(0),
+ exception_code_(0),
+ exception_subcode_(0),
+ exception_thread_(0),
+ crashing_task_(mach_task_self()),
+ handler_thread_(mach_thread_self()),
+ cpu_type_(DynamicImages::GetNativeCPUType()),
+ dyldImageLoadAddress_(NULL),
+ dyldSlide_(0),
+ dyldPath_(),
+ task_context_(NULL),
+ dynamic_images_(NULL),
+ memory_blocks_(&allocator_) {
+ GatherSystemInformation();
+ GatherCurrentProcessDyldInformation();
+}
+
+// constructor when generating from a different process than the
+// crashed process
+MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
+ mach_port_t handler_thread)
+ : writer_(),
+ exception_type_(0),
+ exception_code_(0),
+ exception_subcode_(0),
+ exception_thread_(0),
+ crashing_task_(crashing_task),
+ handler_thread_(handler_thread),
+ cpu_type_(DynamicImages::GetNativeCPUType()),
+ dyldImageLoadAddress_(NULL),
+ dyldSlide_(0),
+ dyldPath_(),
+ task_context_(NULL),
+ dynamic_images_(NULL),
+ memory_blocks_(&allocator_) {
+ if (crashing_task != mach_task_self()) {
+ dynamic_images_ = new DynamicImages(crashing_task_);
+ cpu_type_ = dynamic_images_->GetCPUType();
+ } else {
+ dynamic_images_ = NULL;
+ cpu_type_ = DynamicImages::GetNativeCPUType();
+ }
+
+ GatherSystemInformation();
+ // This constructor is used when creating a crash server, but the crash
+ // server may also be the crashing process.
+ GatherCurrentProcessDyldInformation();
+}
+
+MinidumpGenerator::~MinidumpGenerator() {
+ delete dynamic_images_;
+}
+
+char MinidumpGenerator::build_string_[16];
+int MinidumpGenerator::os_major_version_ = 0;
+int MinidumpGenerator::os_minor_version_ = 0;
+int MinidumpGenerator::os_build_number_ = 0;
+
+// static
+void MinidumpGenerator::GatherSystemInformation() {
+ // If this is non-zero, then we've already gathered the information
+ if (os_major_version_)
+ return;
+
+ // This code extracts the version and build information from the OS
+ CFStringRef vers_path =
+ CFSTR("/System/Library/CoreServices/SystemVersion.plist");
+ CFURLRef sys_vers =
+ CFURLCreateWithFileSystemPath(NULL,
+ vers_path,
+ kCFURLPOSIXPathStyle,
+ false);
+ CFReadStreamRef read_stream = CFReadStreamCreateWithFile(NULL, sys_vers);
+ CFRelease(sys_vers);
+ if (!read_stream) {
+ return;
+ }
+ if (!CFReadStreamOpen(read_stream)) {
+ CFRelease(read_stream);
+ return;
+ }
+ CFMutableDataRef data = NULL;
+ while (true) {
+ // Actual data file tests: Mac at 480 bytes and iOS at 413 bytes.
+ const CFIndex kMaxBufferLength = 1024;
+ UInt8 data_bytes[kMaxBufferLength];
+ CFIndex num_bytes_read =
+ CFReadStreamRead(read_stream, data_bytes, kMaxBufferLength);
+ if (num_bytes_read < 0) {
+ if (data) {
+ CFRelease(data);
+ data = NULL;
+ }
+ break;
+ } else if (num_bytes_read == 0) {
+ break;
+ } else if (!data) {
+ data = CFDataCreateMutable(NULL, 0);
+ }
+ CFDataAppendBytes(data, data_bytes, num_bytes_read);
+ }
+ CFReadStreamClose(read_stream);
+ CFRelease(read_stream);
+ if (!data) {
+ return;
+ }
+ CFDictionaryRef list =
+ static_cast<CFDictionaryRef>(CFPropertyListCreateWithData(
+ NULL, data, kCFPropertyListImmutable, NULL, NULL));
+ CFRelease(data);
+ if (!list) {
+ return;
+ }
+ CFStringRef build_version = static_cast<CFStringRef>
+ (CFDictionaryGetValue(list, CFSTR("ProductBuildVersion")));
+ CFStringRef product_version = static_cast<CFStringRef>
+ (CFDictionaryGetValue(list, CFSTR("ProductVersion")));
+ string build_str = ConvertToString(build_version);
+ string product_str = ConvertToString(product_version);
+
+ CFRelease(list);
+
+ strlcpy(build_string_, build_str.c_str(), sizeof(build_string_));
+
+ // Parse the string that looks like "10.4.8"
+ os_major_version_ = IntegerValueAtIndex(product_str, 0);
+ os_minor_version_ = IntegerValueAtIndex(product_str, 1);
+ os_build_number_ = IntegerValueAtIndex(product_str, 2);
+}
+
+// static
+uint64_t
+MinidumpGenerator::GetCurrentProcessModuleSlide(breakpad_mach_header* mh,
+ uint64_t shared_cache_slide) {
+ if (!mh || (mh->magic != MH_MAGIC_ARCH)) {
+ return 0;
+ }
+
+ if ((mh->flags & MH_SHAREDCACHE) != 0) {
+ return shared_cache_slide;
+ }
+
+ uint64_t slide = 0;
+
+ uint32_t num_commands = mh->ncmds;
+ breakpad_mach_segment_command* cmd = (breakpad_mach_segment_command*)
+ ((uintptr_t)mh + sizeof(breakpad_mach_header));
+ for (uint32_t i = 0; i < num_commands; ++i) {
+ if (cmd->cmd != LC_SEGMENT_ARCH) {
+ break;
+ }
+ if (!cmd->fileoff && cmd->filesize) {
+ slide = (uintptr_t)mh - cmd->vmaddr;
+ break;
+ }
+ cmd = (breakpad_mach_segment_command*) ((uintptr_t)cmd + cmd->cmdsize);
+ }
+
+ return slide;
+}
+
+void MinidumpGenerator::GatherCurrentProcessDyldInformation() {
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ if (task_info(mach_task_self(), TASK_DYLD_INFO,
+ (task_info_t)&task_dyld_info, &count) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_all_image_infos_self* aii = (dyld_all_image_infos_self*)
+ task_dyld_info.all_image_info_addr;
+ breakpad_mach_header* mh = (breakpad_mach_header*) aii->dyldImageLoadAddress;
+ if (!mh || (mh->magic != MH_MAGIC_ARCH)) {
+ return;
+ }
+ dyldImageLoadAddress_ = mh;
+ dyldPath_ = string(aii->dyldPath);
+ dyldSlide_ = GetCurrentProcessModuleSlide(mh, aii->sharedCacheSlide);
+}
+
+void MinidumpGenerator::SetTaskContext(breakpad_ucontext_t *task_context) {
+ task_context_ = task_context;
+}
+
+string MinidumpGenerator::UniqueNameInDirectory(const string &dir,
+ string *unique_name) {
+ CFUUIDRef uuid = CFUUIDCreate(NULL);
+ CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid);
+ CFRelease(uuid);
+ string file_name(ConvertToString(uuid_cfstr));
+ CFRelease(uuid_cfstr);
+ string path(dir);
+
+ // Ensure that the directory (if non-empty) has a trailing slash so that
+ // we can append the file name and have a valid pathname.
+ if (!dir.empty()) {
+ if (dir.at(dir.size() - 1) != '/')
+ path.append(1, '/');
+ }
+
+ path.append(file_name);
+ path.append(".dmp");
+
+ if (unique_name)
+ *unique_name = file_name;
+
+ return path;
+}
+
+bool MinidumpGenerator::Write(const char *path) {
+ WriteStreamFN writers[] = {
+ &MinidumpGenerator::WriteThreadListStream,
+ &MinidumpGenerator::WriteMemoryListStream,
+ &MinidumpGenerator::WriteSystemInfoStream,
+ &MinidumpGenerator::WriteModuleListStream,
+ &MinidumpGenerator::WriteMiscInfoStream,
+ &MinidumpGenerator::WriteBreakpadInfoStream,
+ &MinidumpGenerator::WriteCrashInfoStream,
+ &MinidumpGenerator::WriteBootargsStream,
+ &MinidumpGenerator::WriteThreadNamesStream,
+ // Exception stream needs to be the last entry in this array as it may
+ // be omitted in the case where the minidump is written without an
+ // exception.
+ &MinidumpGenerator::WriteExceptionStream,
+ };
+ bool result = false;
+
+ // If opening was successful, create the header, directory, and call each
+ // writer. The destructor for the TypedMDRVAs will cause the data to be
+ // flushed. The destructor for the MinidumpFileWriter will close the file.
+ if (writer_.Open(path)) {
+ TypedMDRVA<MDRawHeader> header(&writer_);
+ TypedMDRVA<MDRawDirectory> dir(&writer_);
+
+ if (!header.Allocate())
+ return false;
+
+ int writer_count = static_cast<int>(sizeof(writers) / sizeof(writers[0]));
+
+ // If we don't have exception information, don't write out the
+ // exception stream
+ if (!exception_thread_ && !exception_type_)
+ --writer_count;
+
+ // Add space for all writers
+ if (!dir.AllocateArray(writer_count))
+ return false;
+
+ MDRawHeader *header_ptr = header.get();
+ header_ptr->signature = MD_HEADER_SIGNATURE;
+ header_ptr->version = MD_HEADER_VERSION;
+ time(reinterpret_cast<time_t *>(&(header_ptr->time_date_stamp)));
+ header_ptr->stream_count = writer_count;
+ header_ptr->stream_directory_rva = dir.position();
+
+ MDRawDirectory local_dir;
+ result = true;
+ for (int i = 0; (result) && (i < writer_count); ++i) {
+ result = (this->*writers[i])(&local_dir);
+
+ if (result)
+ dir.CopyIndex(i, &local_dir);
+ }
+ }
+ return result;
+}
+
+size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) {
+ mach_vm_address_t stack_region_base = start_addr;
+ mach_vm_size_t stack_region_size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
+
+ if (start_addr == 0) {
+ return 0;
+ }
+
+ kern_return_t result =
+ mach_vm_region_recurse(crashing_task_, &stack_region_base,
+ &stack_region_size, &nesting_level,
+ region_info, &info_count);
+
+ if (result != KERN_SUCCESS || start_addr < stack_region_base) {
+ // Failure or stack corruption, since mach_vm_region had to go
+ // higher in the process address space to find a valid region.
+ return 0;
+ }
+
+ unsigned int tag = submap_info.user_tag;
+
+ // If the user tag is VM_MEMORY_STACK, look for more readable regions with
+ // the same tag placed immediately above the computed stack region. Under
+ // some circumstances, the stack for thread 0 winds up broken up into
+ // multiple distinct abutting regions. This can happen for several reasons,
+ // including user code that calls setrlimit(RLIMIT_STACK, ...) or changes
+ // the access on stack pages by calling mprotect.
+ if (tag == VM_MEMORY_STACK) {
+ while (true) {
+ mach_vm_address_t next_region_base = stack_region_base +
+ stack_region_size;
+ mach_vm_address_t proposed_next_region_base = next_region_base;
+ mach_vm_size_t next_region_size;
+ nesting_level = 0;
+ info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ result = mach_vm_region_recurse(crashing_task_, &next_region_base,
+ &next_region_size, &nesting_level,
+ region_info, &info_count);
+ if (result != KERN_SUCCESS ||
+ next_region_base != proposed_next_region_base ||
+ submap_info.user_tag != tag ||
+ (submap_info.protection & VM_PROT_READ) == 0) {
+ break;
+ }
+
+ stack_region_size += next_region_size;
+ }
+ }
+
+ return stack_region_base + stack_region_size - start_addr;
+}
+
+bool MinidumpGenerator::WriteStackFromStartAddress(
+ mach_vm_address_t start_addr,
+ MDMemoryDescriptor *stack_location) {
+ UntypedMDRVA memory(&writer_);
+
+ bool result = false;
+ size_t size = CalculateStackSize(start_addr);
+
+ if (size == 0) {
+ // In some situations the stack address for the thread can come back 0.
+ // In these cases we skip over the threads in question and stuff the
+ // stack with a clearly borked value.
+ start_addr = 0xDEADBEEF;
+ size = 16;
+ if (!memory.Allocate(size))
+ return false;
+
+ unsigned long long dummy_stack[2]; // Fill dummy stack with 16 bytes of
+ // junk.
+ dummy_stack[0] = 0xDEADBEEF;
+ dummy_stack[1] = 0xDEADBEEF;
+
+ result = memory.Copy(dummy_stack, size);
+ } else {
+
+ if (!memory.Allocate(size))
+ return false;
+
+ if (dynamic_images_) {
+ vector<uint8_t> stack_memory;
+ if (ReadTaskMemory(crashing_task_,
+ start_addr,
+ size,
+ stack_memory) != KERN_SUCCESS) {
+ return false;
+ }
+
+ result = memory.Copy(&stack_memory[0], size);
+ } else {
+ result = memory.Copy(reinterpret_cast<const void *>(start_addr), size);
+ }
+ }
+
+ stack_location->start_of_memory_range = start_addr;
+ stack_location->memory = memory.location();
+
+ return result;
+}
+
+bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return WriteStackARM(state, stack_location);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return WriteStackARM64(state, stack_location);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return WriteStackPPC(state, stack_location);
+ case CPU_TYPE_POWERPC64:
+ return WriteStackPPC64(state, stack_location);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return WriteStackX86(state, stack_location);
+ case CPU_TYPE_X86_64:
+ return WriteStackX86_64(state, stack_location);
+#endif
+ default:
+ return false;
+ }
+}
+
+bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return WriteContextARM(state, register_location);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return WriteContextARM64(state, register_location);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return WriteContextPPC(state, register_location);
+ case CPU_TYPE_POWERPC64:
+ return WriteContextPPC64(state, register_location);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return WriteContextX86(state, register_location);
+ case CPU_TYPE_X86_64:
+ return WriteContextX86_64(state, register_location);
+#endif
+ default:
+ return false;
+ }
+}
+
+uint64_t MinidumpGenerator::CurrentPCForStack(
+ breakpad_thread_state_data_t state) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return CurrentPCForStackARM(state);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return CurrentPCForStackARM64(state);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return CurrentPCForStackPPC(state);
+ case CPU_TYPE_POWERPC64:
+ return CurrentPCForStackPPC64(state);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return CurrentPCForStackX86(state);
+ case CPU_TYPE_X86_64:
+ return CurrentPCForStackX86_64(state);
+#endif
+ default:
+ assert(0 && "Unknown CPU type!");
+ return 0;
+ }
+}
+
+#ifdef HAS_ARM_SUPPORT
+bool MinidumpGenerator::WriteStackARM(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackARM(breakpad_thread_state_data_t state) {
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, pc);
+}
+
+bool MinidumpGenerator::WriteContextARM(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextARM> context(&writer_);
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextARM *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
+
+#define AddGPR(a) context_ptr->iregs[a] = REGISTER_FROM_THREADSTATE(machine_state, r[a])
+
+ context_ptr->iregs[13] = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ context_ptr->iregs[14] = REGISTER_FROM_THREADSTATE(machine_state, lr);
+ context_ptr->iregs[15] = REGISTER_FROM_THREADSTATE(machine_state, pc);
+ context_ptr->cpsr = REGISTER_FROM_THREADSTATE(machine_state, cpsr);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+#undef AddGPR
+
+ return true;
+}
+#endif
+
+#ifdef HAS_ARM64_SUPPORT
+bool MinidumpGenerator::WriteStackARM64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackARM64(breakpad_thread_state_data_t state) {
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, pc);
+}
+
+bool
+MinidumpGenerator::WriteContextARM64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextARM64_Old> context(&writer_);
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextARM64_Old *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+#define AddGPR(a) \
+ context_ptr->iregs[a] = ARRAY_REGISTER_FROM_THREADSTATE(machine_state, x, a)
+
+ context_ptr->iregs[29] = REGISTER_FROM_THREADSTATE(machine_state, fp);
+ context_ptr->iregs[30] = REGISTER_FROM_THREADSTATE(machine_state, lr);
+ context_ptr->iregs[31] = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ context_ptr->iregs[32] = REGISTER_FROM_THREADSTATE(machine_state, pc);
+ context_ptr->cpsr = REGISTER_FROM_THREADSTATE(machine_state, cpsr);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+#undef AddGPR
+
+ return true;
+}
+#endif
+
+#ifdef HAS_PCC_SUPPORT
+bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackPPC(breakpad_thread_state_data_t state) {
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, srr0);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackPPC64(breakpad_thread_state_data_t state) {
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, srr0);
+}
+
+bool MinidumpGenerator::WriteContextPPC(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextPPC> context(&writer_);
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextPPC *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+#define AddGPR(a) context_ptr->gpr[a] = \
+ static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, r ## a)
+
+ AddReg(srr0);
+ AddReg(cr);
+ AddReg(xer);
+ AddReg(ctr);
+ AddReg(lr);
+ AddReg(vrsave);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+ AddGPR(29);
+ AddGPR(30);
+ AddGPR(31);
+ AddReg(mq);
+#undef AddReg
+#undef AddGPR
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteContextPPC64(
+ breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ TypedMDRVA<MDRawContextPPC64> context(&writer_);
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextPPC64 *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+#define AddGPR(a) context_ptr->gpr[a] = \
+ static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, r ## a)
+
+ AddReg(srr0);
+ AddReg(cr);
+ AddReg(xer);
+ AddReg(ctr);
+ AddReg(lr);
+ AddReg(vrsave);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+ AddGPR(29);
+ AddGPR(30);
+ AddGPR(31);
+#undef AddReg
+#undef AddGPR
+
+ return true;
+}
+
+#endif
+
+#ifdef HAS_X86_SUPPORT
+bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ mach_vm_address_t start_addr = static_cast<mach_vm_address_t>(
+ REGISTER_FROM_THREADSTATE(machine_state, rsp));
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackX86(breakpad_thread_state_data_t state) {
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, eip);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackX86_64(breakpad_thread_state_data_t state) {
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, rip);
+}
+
+bool MinidumpGenerator::WriteContextX86(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextX86> context(&writer_);
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextX86 *context_ptr = context.get();
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+
+ context_ptr->context_flags = MD_CONTEXT_X86;
+ AddReg(eax);
+ AddReg(ebx);
+ AddReg(ecx);
+ AddReg(edx);
+ AddReg(esi);
+ AddReg(edi);
+ AddReg(ebp);
+ AddReg(esp);
+
+ AddReg(cs);
+ AddReg(ds);
+ AddReg(ss);
+ AddReg(es);
+ AddReg(fs);
+ AddReg(gs);
+ AddReg(eflags);
+
+ AddReg(eip);
+#undef AddReg
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteContextX86_64(
+ breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ TypedMDRVA<MDRawContextAMD64> context(&writer_);
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextAMD64 *context_ptr = context.get();
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+
+ context_ptr->context_flags = MD_CONTEXT_AMD64;
+ AddReg(rax);
+ AddReg(rbx);
+ AddReg(rcx);
+ AddReg(rdx);
+ AddReg(rdi);
+ AddReg(rsi);
+ AddReg(rbp);
+ AddReg(rsp);
+ AddReg(r8);
+ AddReg(r9);
+ AddReg(r10);
+ AddReg(r11);
+ AddReg(r12);
+ AddReg(r13);
+ AddReg(r14);
+ AddReg(r15);
+ AddReg(rip);
+ // according to AMD's software developer guide, bits above 18 are
+ // not used in the flags register. Since the minidump format
+ // specifies 32 bits for the flags register, we can truncate safely
+ // with no loss.
+ context_ptr->eflags = static_cast<uint32_t>(REGISTER_FROM_THREADSTATE(machine_state, rflags));
+ AddReg(cs);
+ AddReg(fs);
+ AddReg(gs);
+#undef AddReg
+
+ return true;
+}
+#endif
+
+bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
+ thread_state_t state,
+ mach_msg_type_number_t *count) {
+ if (task_context_ && target_thread == mach_thread_self()) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), sizeof(arm_thread_state_t));
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64: {
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), sizeof(arm_thread_state64_t));
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+ }
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ case CPU_TYPE_X86_64: {
+ size_t state_size = cpu_type_ == CPU_TYPE_I386 ?
+ sizeof(i386_thread_state_t) : sizeof(x86_thread_state64_t);
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), state_size);
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+ }
+#endif
+ }
+ }
+
+ thread_state_flavor_t flavor;
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ flavor = ARM_THREAD_STATE;
+ break;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ flavor = ARM_THREAD_STATE64;
+ break;
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ flavor = PPC_THREAD_STATE;
+ break;
+ case CPU_TYPE_POWERPC64:
+ flavor = PPC_THREAD_STATE64;
+ break;
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ flavor = i386_THREAD_STATE;
+ break;
+ case CPU_TYPE_X86_64:
+ flavor = x86_THREAD_STATE64;
+ break;
+#endif
+ default:
+ return false;
+ }
+ return thread_get_state(target_thread, flavor,
+ state, count) == KERN_SUCCESS;
+}
+
+bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
+ MDRawThread *thread) {
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t state_count
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (GetThreadState(thread_id, state, &state_count)) {
+ if (!WriteStack(state, &thread->stack))
+ return false;
+
+ memory_blocks_.push_back(thread->stack);
+
+ if (!WriteContext(state, &thread->thread_context))
+ return false;
+
+ thread->thread_id = thread_id;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadListStream(
+ MDRawDirectory *thread_list_stream) {
+ TypedMDRVA<MDRawThreadList> list(&writer_);
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+ int non_generator_thread_count;
+
+ if (task_threads(crashing_task_, &threads_for_task, &thread_count))
+ return false;
+
+ // Don't include the generator thread
+ if (handler_thread_ != MACH_PORT_NULL)
+ non_generator_thread_count = thread_count - 1;
+ else
+ non_generator_thread_count = thread_count;
+ if (!list.AllocateObjectAndArray(non_generator_thread_count,
+ sizeof(MDRawThread)))
+ return false;
+
+ thread_list_stream->stream_type = MD_THREAD_LIST_STREAM;
+ thread_list_stream->location = list.location();
+
+ list.get()->number_of_threads = non_generator_thread_count;
+
+ MDRawThread thread;
+ int thread_idx = 0;
+
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ memset(&thread, 0, sizeof(MDRawThread));
+
+ if (threads_for_task[i] != handler_thread_) {
+ if (!WriteThreadStream(threads_for_task[i], &thread))
+ return false;
+
+ list.CopyIndexAfterObject(thread_idx++, &thread, sizeof(MDRawThread));
+ }
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteMemoryListStream(
+ MDRawDirectory *memory_list_stream) {
+ TypedMDRVA<MDRawMemoryList> list(&writer_);
+
+ // If the dump has an exception, include some memory around the
+ // instruction pointer.
+ const size_t kIPMemorySize = 256; // bytes
+ bool have_ip_memory = false;
+ MDMemoryDescriptor ip_memory_d;
+ if (exception_thread_ && exception_type_) {
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t stateCount
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (GetThreadState(exception_thread_, state, &stateCount)) {
+ uint64_t ip = CurrentPCForStack(state);
+ // Bound it to the upper and lower bounds of the region
+ // it's contained within. If it's not in a known memory region,
+ // don't bother trying to write it.
+ mach_vm_address_t addr = static_cast<vm_address_t>(ip);
+ mach_vm_size_t size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ vm_region_recurse_info_t recurse_info;
+ recurse_info = reinterpret_cast<vm_region_recurse_info_t>(&info);
+
+ kern_return_t ret =
+ mach_vm_region_recurse(crashing_task_,
+ &addr,
+ &size,
+ &nesting_level,
+ recurse_info,
+ &info_count);
+ if (ret == KERN_SUCCESS && ip >= addr && ip < (addr + size)) {
+ // Try to get 128 bytes before and after the IP, but
+ // settle for whatever's available.
+ ip_memory_d.start_of_memory_range =
+ std::max(uintptr_t(addr),
+ uintptr_t(ip - (kIPMemorySize / 2)));
+ uintptr_t end_of_range =
+ std::min(uintptr_t(ip + (kIPMemorySize / 2)),
+ uintptr_t(addr + size));
+ uintptr_t range_diff = end_of_range -
+ static_cast<uintptr_t>(ip_memory_d.start_of_memory_range);
+ ip_memory_d.memory.data_size = static_cast<uint32_t>(range_diff);
+ have_ip_memory = true;
+ // This needs to get appended to the list even though
+ // the memory bytes aren't filled in yet so the entire
+ // list can be written first. The memory bytes will get filled
+ // in after the memory list is written.
+ memory_blocks_.push_back(ip_memory_d);
+ }
+ }
+ }
+
+ // Now fill in the memory list and write it.
+ size_t memory_count = memory_blocks_.size();
+ if (!list.AllocateObjectAndArray(memory_count,
+ sizeof(MDMemoryDescriptor)))
+ return false;
+
+ memory_list_stream->stream_type = MD_MEMORY_LIST_STREAM;
+ memory_list_stream->location = list.location();
+
+ list.get()->number_of_memory_ranges = static_cast<uint32_t>(memory_count);
+
+ unsigned int i;
+ for (i = 0; i < memory_count; ++i) {
+ list.CopyIndexAfterObject(i, &memory_blocks_[i],
+ sizeof(MDMemoryDescriptor));
+ }
+
+ if (have_ip_memory) {
+ // Now read the memory around the instruction pointer.
+ UntypedMDRVA ip_memory(&writer_);
+ if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
+ return false;
+
+ if (dynamic_images_) {
+ // Out-of-process.
+ vector<uint8_t> memory;
+ if (ReadTaskMemory(crashing_task_,
+ ip_memory_d.start_of_memory_range,
+ ip_memory_d.memory.data_size,
+ memory) != KERN_SUCCESS) {
+ return false;
+ }
+
+ ip_memory.Copy(&memory[0], ip_memory_d.memory.data_size);
+ } else {
+ // In-process, just copy from local memory.
+ ip_memory.Copy(
+ reinterpret_cast<const void *>(ip_memory_d.start_of_memory_range),
+ ip_memory_d.memory.data_size);
+ }
+
+ ip_memory_d.memory = ip_memory.location();
+ // Write this again now that the data location is filled in.
+ list.CopyIndexAfterObject(i - 1, &ip_memory_d,
+ sizeof(MDMemoryDescriptor));
+ }
+
+ return true;
+}
+
+bool
+MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
+ TypedMDRVA<MDRawExceptionStream> exception(&writer_);
+
+ if (!exception.Allocate())
+ return false;
+
+ exception_stream->stream_type = MD_EXCEPTION_STREAM;
+ exception_stream->location = exception.location();
+ MDRawExceptionStream *exception_ptr = exception.get();
+ exception_ptr->thread_id = exception_thread_;
+
+ uint64_t u_exception_code = exception_code_;
+ if (exception_type_ == EXC_CRASH) {
+ if (!IsValidExcCrash(exception_code_)) {
+ return false;
+ }
+
+ [[maybe_unused]] int signal_number;
+ RecoverExceptionDataFromExcCrash(u_exception_code, signal_number);
+ }
+
+ // This naming is confusing, but it is the proper translation from
+ // mach naming to minidump naming.
+ exception_ptr->exception_record.exception_code = exception_type_;
+
+ uint32_t exception_flags = 0;
+ if (exception_type_ == EXC_RESOURCE || exception_type_ == EXC_GUARD) {
+ // For EXC_RESOURCE and EXC_GUARD crashes Crashpad records the uppermost
+ // 32 bits of the exception code in the exception flags, let's do the same
+ // here.
+ exception_flags = u_exception_code >> 32;
+ } else {
+ exception_flags = exception_code_;
+ }
+
+ exception_ptr->exception_record.exception_flags = exception_flags;
+
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t state_count
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (!GetThreadState(exception_thread_, state, &state_count))
+ return false;
+
+ if (!WriteContext(state, &exception_ptr->thread_context))
+ return false;
+
+ if (exception_type_ == EXC_BAD_ACCESS)
+ exception_ptr->exception_record.exception_address = exception_subcode_;
+ else
+ exception_ptr->exception_record.exception_address = CurrentPCForStack(state);
+
+ // Crashpad stores the exception type and the optional exception codes in
+ // the exception information field, so we do the same here.
+ exception_ptr->exception_record.number_parameters =
+ (exception_subcode_ != 0) ? 3 : 2;
+ exception_ptr->exception_record.exception_information[0] = exception_type_;
+ exception_ptr->exception_record.exception_information[1] = exception_code_;
+ exception_ptr->exception_record.exception_information[2] = exception_subcode_;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteSystemInfoStream(
+ MDRawDirectory *system_info_stream) {
+ TypedMDRVA<MDRawSystemInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM;
+ system_info_stream->location = info.location();
+
+ // CPU Information
+ uint32_t number_of_processors;
+ size_t len = sizeof(number_of_processors);
+ sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0);
+ MDRawSystemInfo *info_ptr = info.get();
+
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM;
+ break;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM64_OLD;
+ break;
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC;
+ break;
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ case CPU_TYPE_X86_64:
+ if (cpu_type_ == CPU_TYPE_I386)
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
+ else
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64;
+#ifdef __i386__
+ // ebx is used for PIC code, so we need
+ // to preserve it.
+#define cpuid(op,eax,ebx,ecx,edx) \
+ asm ("pushl %%ebx \n\t" \
+ "cpuid \n\t" \
+ "movl %%ebx,%1 \n\t" \
+ "popl %%ebx" \
+ : "=a" (eax), \
+ "=g" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#elif defined(__x86_64__)
+
+#define cpuid(op,eax,ebx,ecx,edx) \
+ asm ("cpuid \n\t" \
+ : "=a" (eax), \
+ "=b" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+ int unused, unused2;
+ // get vendor id
+ cpuid(0, unused, info_ptr->cpu.x86_cpu_info.vendor_id[0],
+ info_ptr->cpu.x86_cpu_info.vendor_id[2],
+ info_ptr->cpu.x86_cpu_info.vendor_id[1]);
+ // get version and feature info
+ cpuid(1, info_ptr->cpu.x86_cpu_info.version_information, unused, unused2,
+ info_ptr->cpu.x86_cpu_info.feature_information);
+
+ // family
+ info_ptr->processor_level =
+ (info_ptr->cpu.x86_cpu_info.version_information & 0xF00) >> 8;
+ // 0xMMSS (Model, Stepping)
+ info_ptr->processor_revision = static_cast<uint16_t>(
+ (info_ptr->cpu.x86_cpu_info.version_information & 0xF) |
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0) << 4));
+
+ // decode extended model info
+ if (info_ptr->processor_level == 0xF ||
+ info_ptr->processor_level == 0x6) {
+ info_ptr->processor_revision |=
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0000) >> 4);
+ }
+
+ // decode extended family info
+ if (info_ptr->processor_level == 0xF) {
+ info_ptr->processor_level +=
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xFF00000) >> 20);
+ }
+
+#endif // __i386__ || __x86_64_
+ break;
+#endif // HAS_X86_SUPPORT
+ default:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN;
+ break;
+ }
+
+ info_ptr->number_of_processors = static_cast<uint8_t>(number_of_processors);
+#if TARGET_OS_IPHONE
+ info_ptr->platform_id = MD_OS_IOS;
+#else
+ info_ptr->platform_id = MD_OS_MAC_OS_X;
+#endif // TARGET_OS_IPHONE
+
+ MDLocationDescriptor build_string_loc;
+
+ if (!writer_.WriteString(build_string_, 0,
+ &build_string_loc))
+ return false;
+
+ info_ptr->csd_version_rva = build_string_loc.rva;
+ info_ptr->major_version = os_major_version_;
+ info_ptr->minor_version = os_minor_version_;
+ info_ptr->build_number = os_build_number_;
+
+ return true;
+}
+
+// If index == INT_MAX, we're being asked to write dyld in the crashed process.
+bool MinidumpGenerator::WriteModuleStream(unsigned int index,
+ MDRawModule *module) {
+ if (dynamic_images_) {
+ // we're in a different process than the crashed process
+ DynamicImage *image = dynamic_images_->GetImage(index);
+
+ if (!image)
+ return false;
+
+ memset(module, 0, sizeof(MDRawModule));
+
+ MDLocationDescriptor string_location;
+
+ string name = image->GetFilePath();
+ if (!writer_.WriteString(name.c_str(), 0, &string_location))
+ return false;
+
+ module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide();
+ module->size_of_image = static_cast<uint32_t>(image->GetVMSize());
+ module->module_name_rva = string_location.rva;
+
+ // We'll skip the executable module, because they don't have
+ // LC_ID_DYLIB load commands, and the crash processing server gets
+ // version information from the Plist file, anyway.
+ if (index != static_cast<uint32_t>(FindExecutableModule())) {
+ module->version_info.signature = MD_VSFIXEDFILEINFO_SIGNATURE;
+ module->version_info.struct_version |= MD_VSFIXEDFILEINFO_VERSION;
+ // Convert MAC dylib version format, which is a 32 bit number, to the
+ // format used by minidump. The mac format is <16 bits>.<8 bits>.<8 bits>
+ // so it fits nicely into the windows version with some massaging
+ // The mapping is:
+ // 1) upper 16 bits of MAC version go to lower 16 bits of product HI
+ // 2) Next most significant 8 bits go to upper 16 bits of product LO
+ // 3) Least significant 8 bits go to lower 16 bits of product LO
+ uint32_t modVersion = image->GetVersion();
+ module->version_info.file_version_hi = 0;
+ module->version_info.file_version_hi = modVersion >> 16;
+ module->version_info.file_version_lo |= (modVersion & 0xff00) << 8;
+ module->version_info.file_version_lo |= (modVersion & 0xff);
+ }
+
+ if (!WriteCVRecord(module, image->GetCPUType(), image->GetCPUSubtype(),
+ name.c_str(), /* in_memory */ false, /* out_of_process */ true,
+ image->GetIsDyld() || image->GetInDyldSharedCache())) {
+ return false;
+ }
+ } else {
+ // Getting module info in the crashed process
+ const breakpad_mach_header *header;
+ if (index == INT_MAX) {
+ header = dyldImageLoadAddress_;
+ } else {
+ header = (breakpad_mach_header*)_dyld_get_image_header(index);
+ }
+ if (!header)
+ return false;
+
+#ifdef __LP64__
+ assert(header->magic == MH_MAGIC_64);
+
+ if(header->magic != MH_MAGIC_64)
+ return false;
+#else
+ assert(header->magic == MH_MAGIC);
+
+ if(header->magic != MH_MAGIC)
+ return false;
+#endif
+
+ int cpu_type = header->cputype;
+ int cpu_subtype = (header->cpusubtype & ~CPU_SUBTYPE_MASK);
+ bool dyld_or_in_dyld_shared_cache;
+ unsigned long slide;
+ const char* name;
+ if (index == INT_MAX) {
+ dyld_or_in_dyld_shared_cache = true;
+ slide = dyldSlide_;
+ name = dyldPath_.c_str();
+ } else {
+ dyld_or_in_dyld_shared_cache =
+ ((header->flags & MH_SHAREDCACHE) != 0);
+ slide = _dyld_get_image_vmaddr_slide(index);
+ name = _dyld_get_image_name(index);
+ }
+ const struct load_command *cmd =
+ reinterpret_cast<const struct load_command *>(header + 1);
+
+ memset(module, 0, sizeof(MDRawModule));
+
+ for (unsigned int i = 0; cmd && (i < header->ncmds); i++) {
+ if (cmd->cmd == LC_SEGMENT_ARCH) {
+
+ const breakpad_mach_segment_command *seg =
+ reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
+
+ if (!strcmp(seg->segname, "__TEXT")) {
+ MDLocationDescriptor string_location;
+
+ if (!writer_.WriteString(name, 0, &string_location))
+ return false;
+
+ module->base_of_image = seg->vmaddr + slide;
+ module->size_of_image = static_cast<uint32_t>(seg->vmsize);
+ module->module_name_rva = string_location.rva;
+
+ bool in_memory = false;
+#if TARGET_OS_IPHONE
+ in_memory = true;
+#endif
+ if (!WriteCVRecord(module, cpu_type, cpu_subtype, name, in_memory,
+ /* out_of_process */ false,
+ dyld_or_in_dyld_shared_cache)) {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ cmd = reinterpret_cast<struct load_command*>((char *)cmd + cmd->cmdsize);
+ }
+ }
+
+ return true;
+}
+
+int MinidumpGenerator::FindExecutableModule() {
+ if (dynamic_images_) {
+ int index = dynamic_images_->GetExecutableImageIndex();
+
+ if (index >= 0) {
+ return index;
+ }
+ } else {
+ int image_count = _dyld_image_count();
+ const struct mach_header *header;
+
+ for (int index = 0; index < image_count; ++index) {
+ header = _dyld_get_image_header(index);
+
+ if (header->filetype == MH_EXECUTE)
+ return index;
+ }
+ }
+
+ // failed - just use the first image
+ return 0;
+}
+
+bool MinidumpGenerator::IsValidExcCrash(uint64_t exception_code) {
+ switch ((exception_code >> 20) & 0xf) {
+ case EXC_CRASH: // EXC_CRASH cannot wrap EXC_CRASH
+ case EXC_RESOURCE: // EXC_RESOURCE would lose data if wrapped
+ case EXC_GUARD: // EXC_GUARD would lose data if wrapped
+ case EXC_CORPSE_NOTIFY: // EXC_CRASH cannot wrap EXC_CORPSE_NOTIFY
+ return false;
+ default:
+ return true;
+ }
+}
+
+void MinidumpGenerator::RecoverExceptionDataFromExcCrash(
+ uint64_t exception_code, int& signal_number)
+{
+ exception_type_ = (exception_code >> 20) & 0xf;
+ exception_code_ = exception_code & 0xfffff;
+ signal_number = (exception_code >> 24) & 0xff;
+}
+
+bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type, int cpu_subtype,
+ const char *module_path, bool in_memory,
+ bool out_of_process, bool dyld_or_in_dyld_shared_cache) {
+ TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
+
+ // Only return the last path component of the full module path
+ const char *module_name = strrchr(module_path, '/');
+
+ // Increment past the slash
+ if (module_name)
+ ++module_name;
+ else
+ module_name = "<Unknown>";
+
+ size_t module_name_length = strlen(module_name);
+
+ if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(uint8_t)))
+ return false;
+
+ if (!cv.CopyIndexAfterObject(0, module_name, module_name_length))
+ return false;
+
+ module->cv_record = cv.location();
+ MDCVInfoPDB70 *cv_ptr = cv.get();
+ cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
+ cv_ptr->age = 0;
+
+ // Get the module identifier
+ unsigned char identifier[16];
+ bool result = false;
+ bool in_memory_changed = false;
+ // As of macOS 11, most system libraries no longer have separate copies in
+ // the macOS file system. They only exist all lumped together in the "dyld
+ // shared cache", which gets loaded into each process on startup. If one of
+ // our system libraries isn't in the file system, we can only get a UUID
+ // (aka a debug id) for it by looking at a copy of the module loaded into
+ // the crashing process. Setting 'in_memory' to 'true' makes this happen.
+ //
+ // We should be reluctant to change the value of 'in_memory' from 'false' to
+ // 'true'. But we'll sometimes need to do that to work around the problem
+ // discussed above. In any case we only do it if all else has failed. This
+ // resolves https://bugzilla.mozilla.org/show_bug.cgi?id=1662862.
+ //
+ // We're always called in the main process. But the crashing process might
+ // be either the same process or a different one (a child process). If it's
+ // a child process, the modules we'll be looking at are in that process's
+ // memory space, to which we generally don't have access. But because dyld
+ // and the dyld shared cache are loaded into all processes, we do have
+ // access (in child processes) to dyld and modules in the dyld shared cache.
+ // So it's fine to look at these modules. But we must prevent ourselves from
+ // trying to access other child process modules. This resolves
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1676102.
+ while (true) {
+ if (in_memory) {
+ if (out_of_process && !dyld_or_in_dyld_shared_cache) {
+ break;
+ }
+ MacFileUtilities::MachoID macho(module_path,
+ reinterpret_cast<void *>(module->base_of_image),
+ static_cast<size_t>(module->size_of_image));
+ result = macho.UUIDCommand(cpu_type, cpu_subtype, identifier);
+ if (!result)
+ result = macho.MD5(cpu_type, cpu_subtype, identifier);
+ if (result || in_memory_changed)
+ break;
+ }
+
+ if (!result) {
+ FileID file_id(module_path);
+ result = file_id.MachoIdentifier(cpu_type, cpu_subtype,
+ identifier);
+ }
+ if (result)
+ break;
+
+ if (!in_memory) {
+ in_memory = true;
+ in_memory_changed = true;
+ } else
+ break;
+ }
+
+ if (result) {
+ cv_ptr->signature.data1 =
+ static_cast<uint32_t>(identifier[0]) << 24 |
+ static_cast<uint32_t>(identifier[1]) << 16 |
+ static_cast<uint32_t>(identifier[2]) << 8 |
+ static_cast<uint32_t>(identifier[3]);
+ cv_ptr->signature.data2 =
+ static_cast<uint16_t>(identifier[4] << 8) | identifier[5];
+ cv_ptr->signature.data3 =
+ static_cast<uint16_t>(identifier[6] << 8) | identifier[7];
+ cv_ptr->signature.data4[0] = identifier[8];
+ cv_ptr->signature.data4[1] = identifier[9];
+ cv_ptr->signature.data4[2] = identifier[10];
+ cv_ptr->signature.data4[3] = identifier[11];
+ cv_ptr->signature.data4[4] = identifier[12];
+ cv_ptr->signature.data4[5] = identifier[13];
+ cv_ptr->signature.data4[6] = identifier[14];
+ cv_ptr->signature.data4[7] = identifier[15];
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteModuleListStream(
+ MDRawDirectory *module_list_stream) {
+ TypedMDRVA<MDRawModuleList> list(&writer_);
+
+ uint32_t image_count = dynamic_images_ ?
+ dynamic_images_->GetImageCount() :
+ _dyld_image_count();
+
+ // module_count is one higher when we're in the crashed process, to make
+ // room for dyld, which isn't in the standard list of modules. If
+ // dynamic_images_ exists (and we're in a different process than the
+ // crashed process), we've already added dyld to it.
+ uint32_t module_count = dynamic_images_ ? image_count : image_count + 1;
+
+ if (!list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE))
+ return false;
+
+ module_list_stream->stream_type = MD_MODULE_LIST_STREAM;
+ module_list_stream->location = list.location();
+ list.get()->number_of_modules = static_cast<uint32_t>(module_count);
+
+ // Write out the executable module as the first one
+ MDRawModule module;
+ uint32_t executableIndex = FindExecutableModule();
+
+ if (!WriteModuleStream(static_cast<unsigned>(executableIndex), &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(0, &module, MD_MODULE_SIZE);
+ int destinationIndex = 1; // Write all other modules after this one
+
+ if (!dynamic_images_) {
+ // If we're in the crashed process we need to write dyld explicitly,
+ // since it's not included in the standard list. index == INT_MAX signals
+ // our intentions to WriteModuleStream().
+ if (!WriteModuleStream(INT_MAX, &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE);
+ }
+
+ for (uint32_t i = 0; i < image_count; ++i) {
+ if (i != executableIndex) {
+ if (!WriteModuleStream(static_cast<unsigned>(i), &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE);
+ }
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *misc_info_stream) {
+ TypedMDRVA<MDRawMiscInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ misc_info_stream->stream_type = MD_MISC_INFO_STREAM;
+ misc_info_stream->location = info.location();
+
+ MDRawMiscInfo *info_ptr = info.get();
+ info_ptr->size_of_info = static_cast<uint32_t>(sizeof(MDRawMiscInfo));
+ info_ptr->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID |
+ MD_MISCINFO_FLAGS1_PROCESS_TIMES |
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO;
+
+ // Process ID
+ info_ptr->process_id = getpid();
+
+ // Times
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage) != -1) {
+ // Omit the fractional time since the MDRawMiscInfo only wants seconds
+ info_ptr->process_user_time =
+ static_cast<uint32_t>(usage.ru_utime.tv_sec);
+ info_ptr->process_kernel_time =
+ static_cast<uint32_t>(usage.ru_stime.tv_sec);
+ }
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
+ static_cast<int>(info_ptr->process_id) };
+ uint mibsize = static_cast<uint>(sizeof(mib) / sizeof(mib[0]));
+ struct kinfo_proc proc;
+ size_t size = sizeof(proc);
+ if (sysctl(mib, mibsize, &proc, &size, NULL, 0) == 0) {
+ info_ptr->process_create_time =
+ static_cast<uint32_t>(proc.kp_proc.p_starttime.tv_sec);
+ }
+
+ // Speed
+ uint64_t speed;
+ const uint64_t kOneMillion = 1000 * 1000;
+ size = sizeof(speed);
+ sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0);
+ info_ptr->processor_max_mhz = static_cast<uint32_t>(speed / kOneMillion);
+ info_ptr->processor_mhz_limit = static_cast<uint32_t>(speed / kOneMillion);
+ size = sizeof(speed);
+ sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0);
+ info_ptr->processor_current_mhz = static_cast<uint32_t>(speed / kOneMillion);
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteBreakpadInfoStream(
+ MDRawDirectory *breakpad_info_stream) {
+ TypedMDRVA<MDRawBreakpadInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ breakpad_info_stream->stream_type = MD_BREAKPAD_INFO_STREAM;
+ breakpad_info_stream->location = info.location();
+ MDRawBreakpadInfo *info_ptr = info.get();
+
+ if (exception_thread_ && exception_type_) {
+ info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
+ info_ptr->dump_thread_id = handler_thread_;
+ info_ptr->requesting_thread_id = exception_thread_;
+ } else {
+ info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID;
+ info_ptr->dump_thread_id = handler_thread_;
+ info_ptr->requesting_thread_id = 0;
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteCrashInfoRecord(MDLocationDescriptor *location,
+ const char *module_path,
+ const char *crash_info,
+ unsigned long crash_info_size,
+ bool out_of_process,
+ bool dyld_or_in_dyld_shared_cache) {
+ TypedMDRVA<MDRawMacCrashInfoRecord> info(&writer_);
+
+ // Only write crash info records for modules that actually have
+ // __DATA,__crash_info sections.
+ if (!crash_info || !crash_info_size) {
+ return false;
+ }
+ // We generally don't have access to modules in another process's memory
+ // space if the module isn't dyld and isn't in the dyld shared cache.
+ if (out_of_process && !dyld_or_in_dyld_shared_cache) {
+ return false;
+ }
+
+ // If 'crash_info_size' is larger than we expect, 'crash_info' probably
+ // contains fields we don't recognize (added by Apple since we last updated
+ // this code). In that case only copy the fields we do recognize. If it's
+ // smaller than we expect, we're probably running on an older version of
+ // macOS, whose __crash_info sections don't contain all the fields we
+ // recognize. In that case make sure the "missing" fields are zeroed in
+ // 'raw_crash_info'.
+ crashreporter_annotations_t raw_crash_info;
+ bzero(&raw_crash_info, sizeof(raw_crash_info));
+ if (crash_info_size > sizeof(raw_crash_info)) {
+ crash_info_size = sizeof(raw_crash_info);
+ }
+ memcpy(&raw_crash_info, crash_info, crash_info_size);
+
+ // Don't write crash info records that are empty of useful data (see
+ // definition of crashreporter_annotations_t in mach_vm_compat.h).
+ bool is_empty = true;
+ if (raw_crash_info.message ||
+ raw_crash_info.signature_string ||
+ raw_crash_info.backtrace ||
+ raw_crash_info.message2 ||
+ raw_crash_info.thread ||
+ raw_crash_info.dialog_mode ||
+ ((raw_crash_info.version > 4) && raw_crash_info.abort_cause)) {
+ is_empty = false;
+ }
+ if (is_empty) {
+ return false;
+ }
+
+ string message;
+ string signature_string;
+ string backtrace;
+ string message2;
+
+ const char *message_ptr = NULL;
+ const char *signature_string_ptr = NULL;
+ const char *backtrace_ptr = NULL;
+ const char *message2_ptr = NULL;
+
+ if (out_of_process) {
+ if (raw_crash_info.message) {
+ message = ReadTaskString(crashing_task_, raw_crash_info.message);
+ message_ptr = message.c_str();
+ }
+ if (raw_crash_info.signature_string) {
+ signature_string =
+ ReadTaskString(crashing_task_, raw_crash_info.signature_string);
+ signature_string_ptr = signature_string.c_str();
+ }
+ if (raw_crash_info.backtrace) {
+ backtrace = ReadTaskString(crashing_task_, raw_crash_info.backtrace);
+ backtrace_ptr = backtrace.c_str();
+ }
+ if (raw_crash_info.message2) {
+ message2 = ReadTaskString(crashing_task_, raw_crash_info.message2);
+ message2_ptr = message2.c_str();
+ }
+ } else {
+ message_ptr = reinterpret_cast<const char *>(raw_crash_info.message);
+ signature_string_ptr =
+ reinterpret_cast<const char *>(raw_crash_info.signature_string);
+ backtrace_ptr = reinterpret_cast<const char *>(raw_crash_info.backtrace);
+ message2_ptr = reinterpret_cast<const char *>(raw_crash_info.message2);
+ }
+
+ const char* data_strings[] = { module_path, message_ptr,
+ signature_string_ptr, backtrace_ptr,
+ message2_ptr };
+
+ // Compute the total size of the strings we'll be copying to
+ // (MDRawMacCrashInfoRecord).data, including their terminal nulls.
+ size_t data_size = 0;
+ for (auto src : data_strings) {
+ if (!src) {
+ src = "";
+ }
+ // Always include the terminal null, even for an empty string.
+ size_t copy_length = strlen(src) + 1;
+ // A "string" that's too large is a sign of data corruption.
+ if (copy_length > MACCRASHINFO_STRING_MAXSIZE) {
+ return false;
+ }
+ data_size += copy_length;
+ }
+
+ if (!info.AllocateObjectAndArray(data_size, sizeof(uint8_t)))
+ return false;
+
+ // Now copy 'module_path' and the __crash_info strings in order to
+ // (MDRawMacCrashInfoRecord).data, including their terminal nulls.
+ size_t offset = 0;
+ for (auto src : data_strings) {
+ if (!src) {
+ src = "";
+ }
+ // Always include the terminal null, even for an empty string.
+ size_t copy_length = strlen(src) + 1;
+ // We can't use CopyIndexAfterObject() here. Calling that method multiple
+ // times only works for objects in an array (which are all the same size).
+ if (!info.Copy(info.position() + sizeof(MDRawMacCrashInfoRecord) + offset,
+ src, copy_length)) {
+ return false;
+ }
+ offset += copy_length;
+ }
+
+ *location = info.location();
+ MDRawMacCrashInfoRecord *info_ptr = info.get();
+ info_ptr->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ info_ptr->version = raw_crash_info.version;
+ info_ptr->thread = raw_crash_info.thread;
+ info_ptr->dialog_mode = raw_crash_info.dialog_mode;
+ info_ptr->abort_cause = raw_crash_info.abort_cause;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteCrashInfoStream(
+ MDRawDirectory *crash_info_stream) {
+ TypedMDRVA<MDRawMacCrashInfo> list(&writer_);
+
+ if (!list.Allocate())
+ return false;
+
+ crash_info_stream->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ crash_info_stream->location = list.location();
+
+ MDRawMacCrashInfo *list_ptr = list.get();
+ bzero(list_ptr, sizeof(MDRawMacCrashInfo));
+ list_ptr->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ list_ptr->record_start_size = sizeof(MDRawMacCrashInfoRecord);
+
+ uint32_t image_count = dynamic_images_ ?
+ dynamic_images_->GetImageCount() :
+ // Leave room for dyld, which isn't among the images
+ // counted by _dyld_image_count().
+ _dyld_image_count() + 1;
+ uint32_t crash_info_count = 0;
+ for (uint32_t i = 0; (i < image_count) &&
+ (crash_info_count < MAC_CRASH_INFOS_MAX); ++i) {
+ if (dynamic_images_) {
+ // We're in a different process than the crashed process
+ DynamicImage *image = dynamic_images_->GetImage(i);
+ if (!image) {
+ continue;
+ }
+
+ MDLocationDescriptor location;
+ string module_path = image->GetFilePath();
+ // WriteCrashInfoRecord() fails if a module doesn't contain a
+ // __DATA,__crash_info section, or if it's empty of useful data.
+ if (WriteCrashInfoRecord(&location,
+ module_path.c_str(),
+ reinterpret_cast<const char *>
+ (image->GetCrashInfo()),
+ image->GetCrashInfoSize(),
+ /* out_of_process */ true,
+ image->GetInDyldSharedCache() ||
+ image->GetIsDyld())) {
+ list_ptr->records[crash_info_count] = location;
+ ++crash_info_count;
+ }
+ } else {
+ // Getting crash info in the crashed process
+ const breakpad_mach_header *header;
+ // dyld isn't in our list of images, so tack it onto the end.
+ if (i == image_count - 1) {
+ header = dyldImageLoadAddress_;
+ } else {
+ header = (breakpad_mach_header*) _dyld_get_image_header(i);
+ }
+ if (!header || (header->magic != MH_MAGIC_ARCH)) {
+ continue;
+ }
+
+ unsigned long slide;
+ const char *module_path;
+ bool dyld_or_in_dyld_shared_cache;
+ if (i == image_count - 1) {
+ slide = dyldSlide_;
+ module_path = dyldPath_.c_str();
+ dyld_or_in_dyld_shared_cache = true;
+ } else {
+ slide = _dyld_get_image_vmaddr_slide(i);
+ module_path = _dyld_get_image_name(i);
+ dyld_or_in_dyld_shared_cache =
+ ((header->flags & MH_SHAREDCACHE) != 0);
+ }
+
+ getsectdata_size_type crash_info_size = 0;
+ const char *crash_info =
+ getsectdatafromheader_func(header, "__DATA", "__crash_info",
+ &crash_info_size);
+ // __crash_info might be in the __DATA_DIRTY segment.
+ if (!crash_info) {
+ crash_info =
+ getsectdatafromheader_func(header, "__DATA_DIRTY", "__crash_info",
+ &crash_info_size);
+ }
+ if (crash_info) {
+ crash_info += slide;
+ }
+ MDLocationDescriptor location;
+ // WriteCrashInfoRecord() fails if a module doesn't contain a
+ // __DATA,__crash_info section, or if it's empty of useful data.
+ if (WriteCrashInfoRecord(&location, module_path, crash_info,
+ crash_info_size, /* out_of_process */ false,
+ dyld_or_in_dyld_shared_cache)) {
+ list_ptr->records[crash_info_count] = location;
+ ++crash_info_count;
+ }
+ }
+ }
+
+ list_ptr->record_count = crash_info_count;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteBootargsStream(
+ MDRawDirectory *bootargs_stream) {
+ TypedMDRVA<MDRawMacBootargs> info(&writer_);
+ if (!info.Allocate())
+ return false;
+
+ bootargs_stream->stream_type = MOZ_MACOS_BOOTARGS_STREAM;
+ bootargs_stream->location = info.location();
+
+ // We need to write *something* to the stream -- otherwise it will get
+ // corrupted. So if we fail to get kern.bootargs, or if it's empty, write
+ // an empty string -- a single terminal null.
+ size_t size = 0; // Includes terminal null
+ int rv = sysctlbyname("kern.bootargs", NULL, &size, NULL, 0);
+ if ((rv != 0) || (size == 0))
+ size = 1;
+ vector<uint8_t> bootargs(size);
+ bootargs[0] = 0;
+ if (rv == 0)
+ sysctlbyname("kern.bootargs", &bootargs[0], &size, NULL, 0);
+
+ MDLocationDescriptor bootargs_location;
+ const char *bootargs_ptr = reinterpret_cast<const char *>(&bootargs[0]);
+ if (!writer_.WriteString(bootargs_ptr, 0, &bootargs_location))
+ return false;
+
+ MDRawMacBootargs *info_ptr = info.get();
+ info_ptr->stream_type = MOZ_MACOS_BOOTARGS_STREAM;
+ info_ptr->bootargs = bootargs_location.rva;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadName(
+ mach_port_t thread_id,
+ MDRawThreadName *thread_name) {
+ MDLocationDescriptor string_location;
+
+ thread_extended_info_data_t thread_extended_info;
+ mach_msg_type_number_t thread_extended_info_count =
+ THREAD_EXTENDED_INFO_COUNT;
+ kern_return_t res = thread_info(thread_id, THREAD_EXTENDED_INFO,
+ (thread_info_t)&thread_extended_info,
+ &thread_extended_info_count);
+
+ if (res != KERN_SUCCESS)
+ return false;
+
+ if (!writer_.WriteString(thread_extended_info.pth_name, 0, &string_location))
+ return false;
+
+ thread_name->thread_id = thread_id;
+ thread_name->rva_of_thread_name = string_location.rva;
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadNamesStream(
+ MDRawDirectory *thread_names_stream) {
+ TypedMDRVA<MDRawThreadNamesList> list(&writer_);
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(crashing_task_, &threads_for_task, &thread_count))
+ return false;
+
+ int non_generator_thread_count;
+
+ // Don't include the generator thread
+ if (handler_thread_ != MACH_PORT_NULL)
+ non_generator_thread_count = thread_count - 1;
+ else
+ non_generator_thread_count = thread_count;
+
+ if (!list.AllocateObjectAndArray(non_generator_thread_count,
+ sizeof(MDRawThreadName))) {
+ return false;
+ }
+
+ thread_names_stream->stream_type = MD_THREAD_NAMES_STREAM;
+ thread_names_stream->location = list.location();
+
+ list.get()->number_of_thread_names = non_generator_thread_count;
+
+ MDRawThreadName thread_name;
+ int thread_idx = 0;
+
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ memset(&thread_name, 0, sizeof(MDRawThreadName));
+
+ if (threads_for_task[i] != handler_thread_) {
+ if (WriteThreadName(threads_for_task[i], &thread_name)) {
+ list.CopyIndexAfterObject(thread_idx++, &thread_name,
+ sizeof(MDRawThreadName));
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
new file mode 100644
index 0000000000..aba067cc04
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
@@ -0,0 +1,290 @@
+// 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.
+
+// minidump_generator.h: Create a minidump of the current MacOS process.
+
+#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+
+#include <mach/mach.h>
+#include <TargetConditionals.h>
+
+#include <string>
+
+#include "mac/handler/ucontext_compat.h"
+#include "minidump_file_writer.h"
+#include "common/memory_allocator.h"
+#include "common/mac/macho_utilities.h"
+#include "google_breakpad/common/minidump_format.h"
+
+#include "dynamic_images.h"
+#include "mach_vm_compat.h"
+
+#if defined(__arm__)
+#define HAS_ARM_SUPPORT
+#elif defined(__aarch64__)
+#define HAS_ARM64_SUPPORT
+#elif defined(__i386__) || defined(__x86_64__)
+ #define HAS_X86_SUPPORT
+#endif
+
+namespace google_breakpad {
+
+using std::string;
+
+// Use the REGISTER_FROM_THREADSTATE to access a register name from the
+// breakpad_thread_state_t structure.
+#if __DARWIN_OPAQUE_ARM_THREAD_STATE64
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) ((a)->__##b[i])
+#define GET_REGISTER_FROM_THREADSTATE_fp(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_fp))
+#define GET_REGISTER_FROM_THREADSTATE_lr(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_lr))
+#define GET_REGISTER_FROM_THREADSTATE_sp(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_sp))
+#define GET_REGISTER_FROM_THREADSTATE_pc(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_pc))
+#define GET_REGISTER_FROM_THREADSTATE_cpsr(a) ((a)->__cpsr)
+#define GET_REGISTER_FROM_THREADSTATE_flags(a) ((a)->__opaque_flags)
+#define REGISTER_FROM_THREADSTATE(a, b) (GET_REGISTER_FROM_THREADSTATE_##b(a))
+#elif __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64 || TARGET_CPU_ARM
+// In The 10.5 SDK Headers Apple prepended __ to the variable names in the
+// i386_thread_state_t structure. There's no good way to tell what version of
+// the SDK we're compiling against so we just toggle on the same preprocessor
+// symbol Apple's headers use.
+#define REGISTER_FROM_THREADSTATE(a, b) ((a)->__ ## b)
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) \
+ REGISTER_FROM_THREADSTATE(a, b[i])
+#else
+#define REGISTER_FROM_THREADSTATE(a, b) (a->b)
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) \
+ REGISTER_FROM_THREADSTATE(a, b[i])
+#endif
+
+// These typedefs only apply to the current process, whether or not it's the
+// one that crashed.
+#ifdef __LP64__
+typedef dyld_all_image_infos64 dyld_all_image_infos_self;
+#else
+typedef dyld_all_image_infos32 dyld_all_image_infos_self;
+#endif
+
+// Creates a minidump file of the current process. If there is exception data,
+// use SetExceptionInformation() to add this to the minidump. The minidump
+// file is generated by the Write() function.
+// Usage:
+// MinidumpGenerator minidump();
+// minidump.Write("/tmp/minidump");
+//
+class MinidumpGenerator {
+ public:
+ MinidumpGenerator();
+ MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread);
+
+ virtual ~MinidumpGenerator();
+
+ // Return <dir>/<unique_name>.dmp
+ // Sets |unique_name| (if requested) to the unique name for the minidump
+ static string UniqueNameInDirectory(const string &dir, string *unique_name);
+
+ // Write out the minidump into |path|
+ // All of the components of |path| must exist and be writable
+ // Return true if successful, false otherwise
+ bool Write(const char *path);
+
+ // Specify some exception information, if applicable
+ void SetExceptionInformation(int type, int64_t code, int64_t subcode,
+ mach_port_t thread_name) {
+ exception_type_ = type;
+ exception_code_ = code;
+ exception_subcode_ = subcode;
+ exception_thread_ = thread_name;
+ }
+
+ // Specify the task context. If |task_context| is not NULL, it will be used
+ // to retrieve the context of the current thread, instead of using
+ // |thread_get_state|.
+ void SetTaskContext(breakpad_ucontext_t *task_context);
+
+ // Gather system information. This should be call at least once before using
+ // the MinidumpGenerator class.
+ static void GatherSystemInformation();
+
+ // Get the slide for a module in the current process.
+ static uint64_t GetCurrentProcessModuleSlide(breakpad_mach_header* mh,
+ uint64_t shared_cache_slide);
+
+ // Gather information about the dyld module in the current process. This
+ // information is only relevant if the current process is also the crashing
+ // process.
+ void GatherCurrentProcessDyldInformation();
+
+ protected:
+ // Overridable Stream writers
+ virtual bool WriteExceptionStream(MDRawDirectory *exception_stream);
+
+ // Overridable Helper
+ virtual bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
+
+ private:
+ typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
+
+ // Stream writers
+ bool WriteThreadListStream(MDRawDirectory *thread_list_stream);
+ bool WriteMemoryListStream(MDRawDirectory *memory_list_stream);
+ bool WriteSystemInfoStream(MDRawDirectory *system_info_stream);
+ bool WriteModuleListStream(MDRawDirectory *module_list_stream);
+ bool WriteMiscInfoStream(MDRawDirectory *misc_info_stream);
+ bool WriteBreakpadInfoStream(MDRawDirectory *breakpad_info_stream);
+ bool WriteCrashInfoStream(MDRawDirectory *crash_info_stream);
+ bool WriteBootargsStream(MDRawDirectory *bootargs_stream);
+ bool WriteThreadNamesStream(MDRawDirectory *thread_names_stream);
+
+ // Helpers
+ uint64_t CurrentPCForStack(breakpad_thread_state_data_t state);
+ bool GetThreadState(thread_act_t target_thread, thread_state_t state,
+ mach_msg_type_number_t *count);
+ bool WriteStackFromStartAddress(mach_vm_address_t start_addr,
+ MDMemoryDescriptor *stack_location);
+ bool WriteStack(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContext(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ bool WriteCVRecord(MDRawModule *module, int cpu_type, int cpu_subtype,
+ const char *module_path, bool in_memory,
+ bool out_of_process, bool dyld_or_in_dyld_shared_cache);
+ bool WriteModuleStream(unsigned int index, MDRawModule *module);
+ bool WriteCrashInfoRecord(MDLocationDescriptor *location,
+ const char *module_path,
+ const char *crash_info,
+ unsigned long crash_info_size,
+ bool out_of_process,
+ bool dyld_or_in_dyld_shared_cache);
+ bool WriteThreadName(mach_port_t thread_id,
+ MDRawThreadName *thread_name);
+ size_t CalculateStackSize(mach_vm_address_t start_addr);
+ int FindExecutableModule();
+ bool IsValidExcCrash(uint64_t exception_code);
+ void RecoverExceptionDataFromExcCrash(uint64_t exception_code,
+ int& signal_number);
+
+ // Per-CPU implementations of these methods
+#ifdef HAS_ARM_SUPPORT
+ bool WriteStackARM(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextARM(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackARM(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ bool WriteStackARM64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextARM64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackARM64(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ bool WriteStackPPC(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextPPC(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackPPC(breakpad_thread_state_data_t state);
+ bool WriteStackPPC64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextPPC64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackPPC64(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_X86_SUPPORT
+ bool WriteStackX86(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextX86(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackX86(breakpad_thread_state_data_t state);
+ bool WriteStackX86_64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextX86_64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackX86_64(breakpad_thread_state_data_t state);
+#endif
+
+ // disallow copy ctor and operator=
+ explicit MinidumpGenerator(const MinidumpGenerator &);
+ void operator=(const MinidumpGenerator &);
+
+ protected:
+ // Use this writer to put the data to disk
+ MinidumpFileWriter writer_;
+
+ private:
+ // Exception information
+ int exception_type_;
+ int64_t exception_code_;
+ int64_t exception_subcode_;
+ mach_port_t exception_thread_;
+ mach_port_t crashing_task_;
+ mach_port_t handler_thread_;
+
+ // CPU type of the task being dumped.
+ cpu_type_t cpu_type_;
+
+ // System information
+ static char build_string_[16];
+ static int os_major_version_;
+ static int os_minor_version_;
+ static int os_build_number_;
+
+ // Current process dyld information. It only applies to the crashed process
+ // if the current process is the one that crashed. It doesn't apply to the
+ // crashed process if the current process is the crash server and some other
+ // process has crashed.
+ breakpad_mach_header* dyldImageLoadAddress_;
+ ptrdiff_t dyldSlide_;
+ string dyldPath_;
+
+ // Context of the task to dump.
+ breakpad_ucontext_t *task_context_;
+
+ // Information about dynamically loaded code
+ DynamicImages *dynamic_images_;
+
+ // PageAllocator makes it possible to allocate memory
+ // directly from the system, even while handling an exception.
+ mutable PageAllocator allocator_;
+
+ protected:
+ // Blocks of memory written to the dump. These are all currently
+ // written while writing the thread list stream, but saved here
+ // so a memory list stream can be written afterwards.
+ wasteful_vector<MDMemoryDescriptor> memory_blocks_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..1924ac4d58
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
@@ -0,0 +1,843 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8BFC813F11FF9A58002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814411FF9A9C002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814511FF9A9D002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814811FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814911FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814A11FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814B11FF9B3F002CB4DC /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
+ 8BFC814C11FF9B3F002CB4DC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
+ 8BFC81A211FF9C2E002CB4DC /* CPlusTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */; };
+ 8BFC81A311FF9C2F002CB4DC /* CPlusTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */; };
+ 8BFC81AD11FF9C8A002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81AE11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81AF11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81B011FF9C8D002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 9B35FF5A0B267D5F008DE8C7 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ 9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ 9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+ 9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */; };
+ 9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */; };
+ 9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BC1D2940B336F2300F2A2B4 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ 9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ 9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+ 9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */; };
+ 9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */; };
+ 9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+ 9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+ 9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+ 9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0A0B0133520055103E /* exception_handler.h */; };
+ 9BD82C110B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+ 9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0C0B0133520055103E /* minidump_generator.h */; };
+ 9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C240B01344C0055103E /* minidump_file_writer.h */; };
+ 9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+ 9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+ 9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C2C0B01345E0055103E /* string_utilities.h */; };
+ D2F651000BEF947200920385 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ D2F651010BEF947200920385 /* file_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FB0BEF947200920385 /* file_id.h */; };
+ D2F651020BEF947200920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ D2F651030BEF947200920385 /* macho_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FD0BEF947200920385 /* macho_id.h */; };
+ D2F651040BEF947200920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ D2F651050BEF947200920385 /* macho_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FF0BEF947200920385 /* macho_utilities.h */; };
+ D2F651090BEF949A00920385 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ D2F6510A0BEF949A00920385 /* dynamic_images.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F651080BEF949A00920385 /* dynamic_images.h */; };
+ D2F6510E0BEF94EB00920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ D2F6510F0BEF94EB00920385 /* macho_walker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F6510D0BEF94EB00920385 /* macho_walker.h */; };
+ D2F651110BEF951700920385 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ D2F651130BEF951C00920385 /* string_conversion.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9B35FF590B267D5F008DE8C7 /* string_conversion.h */; };
+ D2F651150BEF953000920385 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ D2F651160BEF953100920385 /* convert_UTF.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */; };
+ D2F6511B0BEF970E00920385 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ D2F6511D0BEF973500920385 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ D2F6511E0BEF973600920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ D2F651210BEF975400920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F310E8B07E800D7E813 /* dwarftests.mm */; };
+ F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F390E8B0D0D00D7E813 /* dump_syms.cc */; };
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F760E8B0DC700D7E813 /* bytereader.cc */; };
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */; };
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F780E8B0DC700D7E813 /* functioninfo.cc */; };
+ F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721FA80E8B0E4800D7E813 /* md5.cc */; };
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */; };
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F690486A84900D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */,
+ 9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */,
+ 9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */,
+ 9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */,
+ 9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */,
+ D2F651010BEF947200920385 /* file_id.h in CopyFiles */,
+ D2F651030BEF947200920385 /* macho_id.h in CopyFiles */,
+ D2F651050BEF947200920385 /* macho_utilities.h in CopyFiles */,
+ D2F6510A0BEF949A00920385 /* dynamic_images.h in CopyFiles */,
+ D2F6510F0BEF94EB00920385 /* macho_walker.h in CopyFiles */,
+ D2F651130BEF951C00920385 /* string_conversion.h in CopyFiles */,
+ D2F651160BEF953100920385 /* convert_UTF.h in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 8BFC812011FF99D5002CB4DC /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = usr/lib/libcrypto.dylib; sourceTree = SDKROOT; };
+ 8BFC815411FF9B7F002CB4DC /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
+ 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CPlusTest.framework; path = Library/Frameworks/CPlusTest.framework; sourceTree = DEVELOPER_DIR; };
+ 8DD76F6C0486A84900D96B5E /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convert_UTF.cc; path = ../../../common/convert_UTF.cc; sourceTree = SOURCE_ROOT; };
+ 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = convert_UTF.h; path = ../../../common/convert_UTF.h; sourceTree = SOURCE_ROOT; };
+ 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_conversion.cc; path = ../../../common/string_conversion.cc; sourceTree = SOURCE_ROOT; };
+ 9B35FF590B267D5F008DE8C7 /* string_conversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_conversion.h; path = ../../../common/string_conversion.h; sourceTree = SOURCE_ROOT; };
+ 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+ 9B7CA84E0B1297F200CD3A1D /* unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unit_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer_unittest.cc; path = ../../minidump_file_writer_unittest.cc; sourceTree = "<group>"; };
+ 9BD82A9B0B00267E0055103E /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler_test.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator_test.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C090B0133520055103E /* exception_handler.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C0A0B0133520055103E /* exception_handler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = exception_handler.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C0B0B0133520055103E /* minidump_generator.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C0C0B0133520055103E /* minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_generator.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C230B01344C0055103E /* minidump_file_writer.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer.cc; path = ../../minidump_file_writer.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C240B01344C0055103E /* minidump_file_writer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = minidump_file_writer.h; path = ../../minidump_file_writer.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C2B0B01345E0055103E /* string_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_utilities.cc; path = ../../../common/mac/string_utilities.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C2C0B01345E0055103E /* string_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_utilities.h; path = ../../../common/mac/string_utilities.h; sourceTree = SOURCE_ROOT; };
+ 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "minidump_file_writer-inl.h"; path = "../../minidump_file_writer-inl.h"; sourceTree = SOURCE_ROOT; };
+ D2F650FA0BEF947200920385 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FB0BEF947200920385 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
+ D2F650FC0BEF947200920385 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FD0BEF947200920385 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
+ D2F650FE0BEF947200920385 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FF0BEF947200920385 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
+ D2F651070BEF949A00920385 /* dynamic_images.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dynamic_images.cc; sourceTree = "<group>"; };
+ D2F651080BEF949A00920385 /* dynamic_images.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dynamic_images.h; sourceTree = "<group>"; };
+ D2F6510C0BEF94EB00920385 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
+ D2F6510D0BEF94EB00920385 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = breakpad_exc_server.c; sourceTree = "<group>"; };
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_exc_server.h; sourceTree = "<group>"; };
+ F93A88750E8B4C700026AF89 /* octestcases.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = octestcases.octest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "obj-cTestCases-Info.plist"; sourceTree = "<group>"; };
+ F9721F300E8B07E800D7E813 /* dwarftests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwarftests.h; sourceTree = "<group>"; };
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dwarftests.mm; sourceTree = "<group>"; };
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
+ F9721F390E8B0D0D00D7E813 /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = SOURCE_ROOT; };
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
+ F9721FA80E8B0E4800D7E813 /* md5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = "<group>"; };
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = "<group>"; };
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_64.cc; sourceTree = "<group>"; };
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_64.h; sourceTree = "<group>"; };
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests32-Info.plist"; sourceTree = "<group>"; };
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests64.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests32.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests64-Info.plist"; sourceTree = "<group>"; };
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicImagesTests.h; sourceTree = "<group>"; };
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicImagesTests.cc; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F660486A84900D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */,
+ 8BFC813F11FF9A58002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9B7CA84C0B1297F200CD3A1D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814511FF9A9D002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD82A990B00267E0055103E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */,
+ 8BFC814411FF9A9C002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F93A88720E8B4C700026AF89 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814A11FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC814B11FF9B3F002CB4DC /* SenTestingKit.framework in Frameworks */,
+ 8BFC814C11FF9B3F002CB4DC /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19C00DB04A9500C98454 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814811FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC81A211FF9C2E002CB4DC /* CPlusTest.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B300DBFDBA300505983 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */,
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */,
+ 8BFC814911FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC81A311FF9C2F002CB4DC /* CPlusTest.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* MinidumpWriter */ = {
+ isa = PBXGroup;
+ children = (
+ 8BFC812011FF99D5002CB4DC /* Breakpad.xcconfig */,
+ 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */,
+ 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */,
+ F9721FA80E8B0E4800D7E813 /* md5.cc */,
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */,
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */,
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */,
+ F9721F390E8B0D0D00D7E813 /* dump_syms.cc */,
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */,
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */,
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */,
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */,
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */,
+ D2F6510C0BEF94EB00920385 /* macho_walker.cc */,
+ D2F6510D0BEF94EB00920385 /* macho_walker.h */,
+ D2F651070BEF949A00920385 /* dynamic_images.cc */,
+ D2F651080BEF949A00920385 /* dynamic_images.h */,
+ D2F650FA0BEF947200920385 /* file_id.cc */,
+ D2F650FB0BEF947200920385 /* file_id.h */,
+ D2F650FC0BEF947200920385 /* macho_id.cc */,
+ D2F650FD0BEF947200920385 /* macho_id.h */,
+ D2F650FE0BEF947200920385 /* macho_utilities.cc */,
+ D2F650FF0BEF947200920385 /* macho_utilities.h */,
+ F9C5A41F0DB82DB000209C76 /* testcases */,
+ 9BD82C040B0133420055103E /* Breakpad */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ 9B37CEEA0AF98EB600FA4BD4 /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */,
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */,
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */,
+ );
+ name = MinidumpWriter;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */,
+ 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */,
+ 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76F6C0486A84900D96B5E /* generator_test */,
+ 9BD82A9B0B00267E0055103E /* handler_test */,
+ 9B7CA84E0B1297F200CD3A1D /* unit_test */,
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */,
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */,
+ F93A88750E8B4C700026AF89 /* octestcases.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 9B37CEEA0AF98EB600FA4BD4 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */,
+ 8BFC815411FF9B7F002CB4DC /* Carbon.framework */,
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */,
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */,
+ 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */,
+ 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 9BD82C040B0133420055103E /* Breakpad */ = {
+ isa = PBXGroup;
+ children = (
+ 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */,
+ 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */,
+ 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */,
+ 9B35FF590B267D5F008DE8C7 /* string_conversion.h */,
+ 9BD82C090B0133520055103E /* exception_handler.cc */,
+ 9BD82C0A0B0133520055103E /* exception_handler.h */,
+ 9BD82C0B0B0133520055103E /* minidump_generator.cc */,
+ 9BD82C0C0B0133520055103E /* minidump_generator.h */,
+ 9BD82C230B01344C0055103E /* minidump_file_writer.cc */,
+ 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */,
+ 9BD82C240B01344C0055103E /* minidump_file_writer.h */,
+ 9BD82C2B0B01345E0055103E /* string_utilities.cc */,
+ 9BD82C2C0B01345E0055103E /* string_utilities.h */,
+ );
+ name = Breakpad;
+ sourceTree = "<group>";
+ };
+ F9C5A41F0DB82DB000209C76 /* testcases */ = {
+ isa = PBXGroup;
+ children = (
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */,
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */,
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */,
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */,
+ F9721F300E8B07E800D7E813 /* dwarftests.h */,
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */,
+ );
+ path = testcases;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F620486A84900D96B5E /* generator_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */;
+ buildPhases = (
+ 8DD76F640486A84900D96B5E /* Sources */,
+ 8DD76F660486A84900D96B5E /* Frameworks */,
+ 8DD76F690486A84900D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = generator_test;
+ productInstallPath = "$(HOME)/bin";
+ productName = MinidumpWriter;
+ productReference = 8DD76F6C0486A84900D96B5E /* generator_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ 9B7CA84D0B1297F200CD3A1D /* unit_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */;
+ buildPhases = (
+ 9B7CA84B0B1297F200CD3A1D /* Sources */,
+ 9B7CA84C0B1297F200CD3A1D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = unit_test;
+ productName = "filewriter unit test";
+ productReference = 9B7CA84E0B1297F200CD3A1D /* unit_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ 9BD82A9A0B00267E0055103E /* handler_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */;
+ buildPhases = (
+ 9BD82A980B00267E0055103E /* Sources */,
+ 9BD82A990B00267E0055103E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = handler_test;
+ productName = ExceptionTester;
+ productReference = 9BD82A9B0B00267E0055103E /* handler_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */;
+ buildPhases = (
+ F93A88700E8B4C700026AF89 /* Resources */,
+ F93A88710E8B4C700026AF89 /* Sources */,
+ F93A88720E8B4C700026AF89 /* Frameworks */,
+ F93A88730E8B4C700026AF89 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "obj-c_TestCases";
+ productName = octestcases;
+ productReference = F93A88750E8B4C700026AF89 /* octestcases.octest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */;
+ buildPhases = (
+ F9AE19BE0DB04A9500C98454 /* Resources */,
+ F9AE19BF0DB04A9500C98454 /* Sources */,
+ F9AE19C00DB04A9500C98454 /* Frameworks */,
+ F9AE19C10DB04A9500C98454 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests64;
+ productName = minidump_tests;
+ productReference = F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */;
+ buildPhases = (
+ F9AE5B2E0DBFDBA300505983 /* Resources */,
+ F9AE5B2F0DBFDBA300505983 /* Sources */,
+ F9AE5B300DBFDBA300505983 /* Frameworks */,
+ F9AE5B310DBFDBA300505983 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests32;
+ productName = Untitled;
+ productReference = F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* MinidumpWriter */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DD76F620486A84900D96B5E /* generator_test */,
+ 9BD82A9A0B00267E0055103E /* handler_test */,
+ 9B7CA84D0B1297F200CD3A1D /* unit_test */,
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */,
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */,
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ F93A88700E8B4C700026AF89 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BE0DB04A9500C98454 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2E0DBFDBA300505983 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F93A88730E8B4C700026AF89 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
+ };
+ F9AE19C10DB04A9500C98454 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n# Run gcov on the framework getting tested\nif [ \"${CONFIGURATION}\" = 'Coverage' ];\nthen\n FRAMEWORK_NAME=minidump_tests64\n FRAMEWORK_OBJ_DIR=${OBJROOT}/${PROJECT_NAME}.build/${CONFIGURATION}/${FRAMEWORK_NAME}.build/Objects-normal/${NATIVE_ARCH_ACTUAL}\n mkdir -p coverage\n pushd coverage\n echo find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n popd\nfi ";
+ };
+ F9AE5B310DBFDBA300505983 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F640486A84900D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */,
+ 9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */,
+ 9BD82C110B0133520055103E /* minidump_generator.cc in Sources */,
+ 9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */,
+ 9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */,
+ D2F651000BEF947200920385 /* file_id.cc in Sources */,
+ D2F651020BEF947200920385 /* macho_id.cc in Sources */,
+ D2F651040BEF947200920385 /* macho_utilities.cc in Sources */,
+ D2F651090BEF949A00920385 /* dynamic_images.cc in Sources */,
+ D2F6510E0BEF94EB00920385 /* macho_walker.cc in Sources */,
+ D2F651110BEF951700920385 /* string_conversion.cc in Sources */,
+ D2F651150BEF953000920385 /* convert_UTF.cc in Sources */,
+ 8BFC81B011FF9C8D002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9B7CA84B0B1297F200CD3A1D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */,
+ 9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */,
+ 9BC1D2940B336F2300F2A2B4 /* convert_UTF.cc in Sources */,
+ 9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */,
+ 8BFC81AE11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD82A980B00267E0055103E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */,
+ 9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */,
+ 9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */,
+ 9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */,
+ 9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */,
+ 9B35FF5A0B267D5F008DE8C7 /* convert_UTF.cc in Sources */,
+ 9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */,
+ D2F6511B0BEF970E00920385 /* dynamic_images.cc in Sources */,
+ D2F6511D0BEF973500920385 /* file_id.cc in Sources */,
+ D2F6511E0BEF973600920385 /* macho_id.cc in Sources */,
+ D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */,
+ D2F651210BEF975400920385 /* macho_walker.cc in Sources */,
+ 8BFC81AF11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F93A88710E8B4C700026AF89 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */,
+ F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */,
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */,
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */,
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */,
+ F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */,
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */,
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */,
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */,
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BF0DB04A9500C98454 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */,
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */,
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */,
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2F0DBFDBA300505983 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */,
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */,
+ 8BFC81AD11FF9C8A002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB923208733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
+ );
+ PRODUCT_NAME = generator_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Debug;
+ };
+ 1DEB923308733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
+ );
+ PRODUCT_NAME = generator_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Release;
+ };
+ 1DEB923608733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB923708733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ 9B7CA8510B12984300CD3A1D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = unit_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Debug;
+ };
+ 9B7CA8520B12984300CD3A1D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = unit_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Release;
+ };
+ 9BD82AA70B0026BF0055103E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = handler_test;
+ USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+ };
+ name = Debug;
+ };
+ 9BD82AA80B0026BF0055103E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = handler_test;
+ USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+ };
+ name = Release;
+ };
+ F93A88770E8B4C700026AF89 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Debug;
+ };
+ F93A88780E8B4C700026AF89 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Release;
+ };
+ F9AE19C40DB04A9500C98454 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ PRODUCT_NAME = minidump_tests64;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE19C50DB04A9500C98454 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ PRODUCT_NAME = minidump_tests64;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Release;
+ };
+ F9AE5B350DBFDBA300505983 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE5B370DBFDBA300505983 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923208733DC60010E9CD /* Debug */,
+ 1DEB923308733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923608733DC60010E9CD /* Debug */,
+ 1DEB923708733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9B7CA8510B12984300CD3A1D /* Debug */,
+ 9B7CA8520B12984300CD3A1D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9BD82AA70B0026BF0055103E /* Debug */,
+ 9BD82AA80B0026BF0055103E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F93A88770E8B4C700026AF89 /* Debug */,
+ F93A88780E8B4C700026AF89 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE19C40DB04A9500C98454 /* Debug */,
+ F9AE19C50DB04A9500C98454 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE5B350DBFDBA300505983 /* Debug */,
+ F9AE5B370DBFDBA300505983 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/moz.build b/toolkit/crashreporter/breakpad-client/mac/handler/moz.build
new file mode 100644
index 0000000000..7d123a2ef1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/moz.build
@@ -0,0 +1,22 @@
+# -*- 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/.
+
+UNIFIED_SOURCES += [
+ 'breakpad_nlist_64.cc',
+ 'dynamic_images.cc',
+ 'exception_handler.cc',
+ 'minidump_generator.cc',
+]
+
+FINAL_LIBRARY = 'breakpad_client'
+
+LOCAL_INCLUDES += [
+ '/toolkit/crashreporter/breakpad-client',
+ '/toolkit/crashreporter/google-breakpad/src',
+]
+
+if CONFIG['MOZ_PHC']:
+ DEFINES['MOZ_PHC'] = True
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc
new file mode 100644
index 0000000000..6142ad124a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc
@@ -0,0 +1,92 @@
+// 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.
+//
+// ProtectedMemoryAllocator
+//
+// See the header file for documentation
+
+#include "protected_memory_allocator.h"
+#include <assert.h>
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ProtectedMemoryAllocator::ProtectedMemoryAllocator(vm_size_t pool_size)
+ : pool_size_(pool_size),
+ next_alloc_offset_(0),
+ valid_(false) {
+
+ kern_return_t result = vm_allocate(mach_task_self(),
+ &base_address_,
+ pool_size,
+ TRUE
+ );
+
+ valid_ = (result == KERN_SUCCESS);
+ assert(valid_);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ProtectedMemoryAllocator::~ProtectedMemoryAllocator() {
+ vm_deallocate(mach_task_self(),
+ base_address_,
+ pool_size_
+ );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+char *ProtectedMemoryAllocator::Allocate(vm_size_t bytes) {
+ if (valid_ && next_alloc_offset_ + bytes <= pool_size_) {
+ char *p = (char*)base_address_ + next_alloc_offset_;
+ next_alloc_offset_ += bytes;
+ return p;
+ }
+
+ return NULL; // ran out of memory in our allocation block
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+kern_return_t ProtectedMemoryAllocator::Protect() {
+ kern_return_t result = vm_protect(mach_task_self(),
+ base_address_,
+ pool_size_,
+ FALSE,
+ VM_PROT_READ);
+
+ return result;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+kern_return_t ProtectedMemoryAllocator::Unprotect() {
+ kern_return_t result = vm_protect(mach_task_self(),
+ base_address_,
+ pool_size_,
+ FALSE,
+ VM_PROT_READ | VM_PROT_WRITE);
+
+ return result;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h
new file mode 100644
index 0000000000..64ac23c00b
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h
@@ -0,0 +1,85 @@
+// 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.
+//
+// ProtectedMemoryAllocator
+//
+// A very simple allocator class which allows allocation, but not deallocation.
+// The allocations can be made read-only with the Protect() method.
+// This class is NOT useful as a general-purpose memory allocation system,
+// since it does not allow deallocation. It is useful to use for a group
+// of allocations which are created in the same time-frame and destroyed
+// in the same time-frame. It is useful for making allocations of memory
+// which will not need to change often once initialized. This memory can then
+// be protected from memory smashers by calling the Protect() method.
+
+#ifndef PROTECTED_MEMORY_ALLOCATOR_H__
+#define PROTECTED_MEMORY_ALLOCATOR_H__
+
+#include <mach/mach.h>
+
+//
+class ProtectedMemoryAllocator {
+ public:
+ ProtectedMemoryAllocator(vm_size_t pool_size);
+ ~ProtectedMemoryAllocator();
+
+ // Returns a pointer to an allocation of size n within the pool.
+ // Fails by returning NULL is no more space is available.
+ // Please note that the pointers returned from this method should not
+ // be freed in any way (for example by calling free() on them ).
+ char * Allocate(vm_size_t n);
+
+ // Returns the base address of the allocation pool.
+ char * GetBaseAddress() { return (char*)base_address_; }
+
+ // Returns the size of the allocation pool, including allocated
+ // plus free space.
+ vm_size_t GetTotalSize() { return pool_size_; }
+
+ // Returns the number of bytes already allocated in the pool.
+ vm_size_t GetAllocatedSize() { return next_alloc_offset_; }
+
+ // Returns the number of bytes available for allocation.
+ vm_size_t GetFreeSize() { return pool_size_ - next_alloc_offset_; }
+
+ // Makes the entire allocation pool read-only including, of course,
+ // all allocations made from the pool.
+ kern_return_t Protect();
+
+ // Makes the entire allocation pool read/write.
+ kern_return_t Unprotect();
+
+ private:
+ vm_size_t pool_size_;
+ vm_address_t base_address_;
+ vm_size_t next_alloc_offset_;
+ bool valid_;
+};
+
+#endif // PROTECTED_MEMORY_ALLOCATOR_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc
new file mode 100644
index 0000000000..42344ec5d3
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2008, 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.
+
+//
+// DynamicImagesTests.cpp
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/17/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#include "mac/handler/testcases/DynamicImagesTests.h"
+#include "mac/handler/dynamic_images.h"
+
+DynamicImagesTests test2(TEST_INVOCATION(DynamicImagesTests,
+ ReadTaskMemoryTest));
+DynamicImagesTests test3(TEST_INVOCATION(DynamicImagesTests,
+ ReadLibrariesFromLocalTaskTest));
+
+DynamicImagesTests::DynamicImagesTests(TestInvocation *invocation)
+ : TestCase(invocation) {
+}
+
+DynamicImagesTests::~DynamicImagesTests() {
+}
+
+void DynamicImagesTests::ReadTaskMemoryTest() {
+ kern_return_t kr;
+
+ // pick test2 as a symbol we know to be valid to read
+ // anything will work, really
+ void *addr = reinterpret_cast<void*>(&test2);
+ std::vector<uint8_t> buf(getpagesize());
+
+ fprintf(stderr, "reading 0x%p\n", addr);
+ kr = google_breakpad::ReadTaskMemory(mach_task_self(),
+ (uint64_t)addr,
+ getpagesize(),
+ buf);
+
+ CPTAssert(kr == KERN_SUCCESS);
+
+ CPTAssert(0 == memcmp(&buf[0], (const void*)addr, getpagesize()));
+}
+
+void DynamicImagesTests::ReadLibrariesFromLocalTaskTest() {
+
+ mach_port_t me = mach_task_self();
+ google_breakpad::DynamicImages *d = new google_breakpad::DynamicImages(me);
+
+ fprintf(stderr,"Local task image count: %d\n", d->GetImageCount());
+
+ CPTAssert(d->GetImageCount() > 0);
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h
new file mode 100644
index 0000000000..e1e79993bb
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2008, 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.
+
+//
+// DynamicImagesTests.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/17/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+//
+
+#ifndef _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__
+#define _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__
+
+#include <CPlusTest/CPlusTest.h>
+
+class DynamicImagesTests : public TestCase {
+ public:
+ explicit DynamicImagesTests(TestInvocation* invocation);
+ virtual ~DynamicImagesTests();
+
+ void ReadTaskMemoryTest();
+ void ReadLibrariesFromLocalTaskTest();
+};
+
+#endif /* _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__ */
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc
new file mode 100644
index 0000000000..ee3248116d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2008, 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.
+
+//
+// breakpad_nlist_test.cc
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/13/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#include "mac/handler/testcases/breakpad_nlist_test.h"
+#include <mach-o/nlist.h>
+#include "mac/handler/breakpad_nlist_64.h"
+
+BreakpadNlistTest test1(TEST_INVOCATION(BreakpadNlistTest, CompareToNM));
+
+BreakpadNlistTest::BreakpadNlistTest(TestInvocation *invocation)
+ : TestCase(invocation) {
+}
+
+
+BreakpadNlistTest::~BreakpadNlistTest() {
+}
+
+void BreakpadNlistTest::CompareToNM() {
+#if TARGET_CPU_X86_64
+ system("/usr/bin/nm -arch x86_64 /usr/lib/dyld > /tmp/dyld-namelist.txt");
+#elif TARGET_CPU_PPC64
+ system("/usr/bin/nm -arch ppc64 /usr/lib/dyld > /tmp/dyld-namelist.txt");
+#endif
+
+ FILE *fd = fopen("/tmp/dyld-namelist.txt", "rt");
+
+ char oneNMAddr[30];
+ char symbolType;
+ char symbolName[500];
+ while (!feof(fd)) {
+ fscanf(fd, "%s %c %s", oneNMAddr, &symbolType, symbolName);
+ breakpad_nlist symbolList[2];
+ breakpad_nlist &list = symbolList[0];
+
+ memset(symbolList, 0, sizeof(breakpad_nlist)*2);
+ const char *symbolNames[2];
+ symbolNames[0] = (const char*)symbolName;
+ symbolNames[1] = "\0";
+ breakpad_nlist_64("/usr/lib/dyld", &list, symbolNames);
+ uint64_t nmAddr = strtol(oneNMAddr, NULL, 16);
+ if (!IsSymbolMoreThanOnceInDyld(symbolName)) {
+ CPTAssert(nmAddr == symbolList[0].n_value);
+ }
+ }
+
+ fclose(fd);
+}
+
+bool BreakpadNlistTest::IsSymbolMoreThanOnceInDyld(const char *symbolName) {
+ // These are the symbols that occur more than once when nm dumps
+ // the symbol table of /usr/lib/dyld. Our nlist program returns
+ // the first address because it's doing a search so we need to exclude
+ // these from causing the test to fail
+ const char *multipleSymbols[] = {
+ "__Z41__static_initialization_and_destruction_0ii",
+ "___tcf_0",
+ "___tcf_1",
+ "_read_encoded_value_with_base",
+ "_read_sleb128",
+ "_read_uleb128",
+ "\0"};
+
+ bool found = false;
+
+ for (int i = 0; multipleSymbols[i][0]; i++) {
+ if (!strcmp(multipleSymbols[i], symbolName)) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h
new file mode 100644
index 0000000000..e93657cc90
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2008, 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.
+
+//
+// breakpad_nlist_test.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/13/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+//
+
+#ifndef CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__
+#define CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__
+
+#include <CPlusTest/CPlusTest.h>
+
+class BreakpadNlistTest : public TestCase {
+ private:
+
+ // nm dumps multiple addresses for the same symbol in
+ // /usr/lib/dyld. So we track those so we don't report failures
+ // in mismatches between what our nlist returns and what nm has
+ // for the duplicate symbols.
+ bool IsSymbolMoreThanOnceInDyld(const char *symbolName);
+
+ public:
+ explicit BreakpadNlistTest(TestInvocation* invocation);
+ virtual ~BreakpadNlistTest();
+
+
+ /* This test case runs nm on /usr/lib/dyld and then compares the
+ output of every symbol to what our nlist implementation returns */
+ void CompareToNM();
+};
+
+#endif /* CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__*/
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h
new file mode 100644
index 0000000000..21ff7a44f0
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2008, 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.
+
+//
+// dwarftests.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 9/24/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#import <SenTestingKit/SenTestingKit.h>
+
+
+@interface dwarftests : SenTestCase {
+
+}
+
+- (void) testDWARFSymbolFileGeneration;
+
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm
new file mode 100644
index 0000000000..40c69aff25
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm
@@ -0,0 +1,60 @@
+// Copyright (c) 2008, 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.
+
+//
+// dwarftests.m
+// minidump_test
+//
+// Created by Neal Sidhwaney on 9/24/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#import "dwarftests.h"
+#import "dump_syms.h"
+
+@implementation dwarftests
+- (void) testDWARFSymbolFileGeneration {
+ NSString *inputBreakpadSymbolFile = @"testcases/testdata/dump_syms_i386_breakpad.sym";
+ NSString *outputBreakpadSymbolFile = @"/tmp/dump_syms_i386.breakpad";
+
+ DumpSymbols *dump = [[DumpSymbols alloc] initWithContentsOfFile:@"testcases/testdata/dump_syms_dwarf_data"];
+
+ STAssertNotNil(dump, @"DumpSymbols is nil");
+ [dump setArchitecture:@"i386"];
+ [dump writeSymbolFile:outputBreakpadSymbolFile];
+
+ NSData *d = [[NSData alloc] initWithContentsOfFile:inputBreakpadSymbolFile];
+ STAssertNotNil(d, @"Input breakpad symbol file not found");
+
+ NSData *d1 = [[NSData alloc] initWithContentsOfFile:outputBreakpadSymbolFile];
+ STAssertNotNil(d1, @"Output breakpad symbol file not found");
+
+ STAssertTrue([d isEqualToData:d1],
+ @"Symbol files were not equal!",nil);
+}
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data
new file mode 100644
index 0000000000..5be17aeedc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data
Binary files differ
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym
new file mode 100644
index 0000000000..bca43c1037
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym
@@ -0,0 +1,5300 @@
+MODULE mac x86 94BF873C47A73BC07125291390B4C5F10 dump_syms_dwarf_data
+FILE 1 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 2 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 3 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dump_syms.mm
+FILE 4 /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSRange.h
+FILE 5 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/new
+FILE 6 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_fun.h
+FILE 7 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 8 ../../../common/mac/file_id.h
+FILE 9 ../../../common/mac/dwarf/functioninfo.h
+FILE 10 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h
+FILE 11 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 12 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h
+FILE 13 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 14 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 15 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h
+FILE 16 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 17 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h
+FILE 18 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h
+FILE 19 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algo.h
+FILE 20 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h
+FILE 21 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 22 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h
+FILE 23 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map
+FILE 24 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h
+FILE 25 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 26 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h
+FILE 27 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc
+FILE 28 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 29 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 30 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/functioninfo.cc
+FILE 31 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 32 ../../../common/mac/dwarf/functioninfo.h
+FILE 33 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 34 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h
+FILE 35 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory
+FILE 36 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 37 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h
+FILE 38 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 39 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 40 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h
+FILE 41 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h
+FILE 42 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map
+FILE 43 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 44 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 45 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h
+FILE 46 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 47 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 48 /g/code/breakpad-staging/src/tools/mac/dump_syms/dump_syms_tool.mm
+FILE 49 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/file_id.cc
+FILE 50 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 51 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_id.cc
+FILE 52 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 53 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 54 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_walker.cc
+FILE 55 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 56 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 57 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_utilities.cc
+FILE 58 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/bytereader.cc
+FILE 59 ../../../common/mac/dwarf/bytereader-inl.h
+FILE 60 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/dwarf2reader.cc
+FILE 61 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 62 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_deque.h
+FILE 63 ../../../common/mac/dwarf/bytereader.h
+FILE 64 ../../../common/mac/dwarf/bytereader-inl.h
+FILE 65 ../../../common/mac/dwarf/line_state_machine.h
+FILE 66 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h
+FILE 67 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory
+FILE 68 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 69 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h
+FILE 70 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 71 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 72 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 73 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 74 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 75 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_stack.h
+FILE 76 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/deque.tcc
+FILE 77 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc
+FILE 78 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 79 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 80 /var/tmp/gcc/gcc-5484~1/src/gcc/libgcc2.c
+FUNC 162a 28 0 _OSSwapInt16
+162a 10 44 55
+163a 16 46 55
+1650 2 47 55
+FUNC 1652 1c 0 _OSSwapInt32
+1652 f 53 55
+1661 8 55 55
+1669 3 56 55
+166c 2 57 55
+FUNC 166e 2b 0 _OSSwapInt64
+166e 12 64 55
+1680 11 69 55
+1691 6 70 55
+1697 2 71 55
+1699 1 71 55
+FUNC 169a 1e 0 NXSwapShort
+169a 10 43 56
+16aa c 45 56
+16b6 2 46 56
+FUNC 16b8 19 0 NXSwapInt
+16b8 f 52 56
+16c7 8 54 56
+16cf 2 55 56
+16d1 1 55 56
+FUNC 16d2 19 0 NXSwapLong
+16d2 f 61 56
+16e1 8 63 56
+16e9 2 64 56
+16eb 1 64 56
+FUNC 16ec 1f 0 NXSwapLongLong
+16ec 12 70 56
+16fe b 72 56
+1709 2 73 56
+170b 1 73 56
+FUNC 170c 181 0 -[DumpSymbols convertCPlusPlusSymbols:]
+170c 14 128 3
+1720 54 130 3
+1774 f 132 3
+1783 7 133 3
+178a 1a 136 3
+17a4 5 138 3
+17a9 1a 139 3
+17c3 23 140 3
+17e6 7 141 3
+17ed 44 142 3
+1831 1e 145 3
+184f 29 138 3
+1878 b 148 3
+1883 3 150 3
+1886 7 151 3
+188d 1 151 3
+FUNC 188e 323 0 -[DumpSymbols convertSymbols]
+188e 14 154 3
+18a2 1f 155 3
+18c1 3e 156 3
+18ff 2b 160 3
+192a c 162 3
+1936 43 164 3
+1979 2a 165 3
+19a3 20 168 3
+19c3 d 169 3
+19d0 1e 171 3
+19ee 11 162 3
+19ff 7 181 3
+1a06 6 182 3
+1a0c 5 184 3
+1a11 15 185 3
+1a26 6 18 4
+1a2c 6 19 4
+1a32 6 20 4
+1a38 6 185 3
+1a3e 28 186 3
+1a66 21 187 3
+1a87 1a 188 3
+1aa1 a 190 3
+1aab c 194 3
+1ab7 43 198 3
+1afa 21 199 3
+1b1b 20 202 3
+1b3b 2e 203 3
+1b69 1e 194 3
+1b87 c 184 3
+1b93 17 207 3
+1baa 7 208 3
+1bb1 1 208 3
+FUNC 1bb2 4a2 0 -[DumpSymbols addFunction:line:address:section:]
+1bb2 21 211 3
+1bd3 2f 212 3
+1c02 e 214 3
+1c10 4 219 3
+1c14 2a 221 3
+1c3e 22 223 3
+1c60 6 224 3
+1c66 2a 225 3
+1c90 4 226 3
+1c94 2e 230 3
+1cc2 2e 233 3
+1cf0 2e 236 3
+1d1e a 239 3
+1d28 2b 253 3
+1d53 e 254 3
+1d61 3c 255 3
+1d9d 22 32 4
+1dbf 3 256 3
+1dc2 6 259 3
+1dc8 a 260 3
+1dd2 3c 261 3
+1e0e 25 262 3
+1e33 2a 263 3
+1e5d 22 265 3
+1e7f 26 270 3
+1ea5 6 272 3
+1eab 37 273 3
+1ee2 2a 274 3
+1f0c 17 275 3
+1f23 43 278 3
+1f66 2e 279 3
+1f94 23 282 3
+1fb7 43 285 3
+1ffa 52 287 3
+204c 8 289 3
+FUNC 2054 5a4 0 -[DumpSymbols processSymbolItem:stringTable:]
+2054 18 292 3
+206c 8 293 3
+2074 4 294 3
+2078 16 297 3
+208e c 298 3
+209a f 300 3
+20a9 b 301 3
+20b4 16 303 3
+20ca 4d 309 3
+2117 38 311 3
+214f 30 315 3
+217f 60 317 3
+21df d 322 3
+21ec 2b 325 3
+2217 3a 327 3
+2251 f 332 3
+2260 2d 333 3
+228d 1a 334 3
+22a7 32 335 3
+22d9 20 342 3
+22f9 c 343 3
+2305 24 348 3
+2329 a 349 3
+2333 3c 350 3
+236f 2a 352 3
+2399 1c 353 3
+23b5 9 354 3
+23be f 356 3
+23cd 2d 357 3
+23fa 2f 358 3
+2429 20 360 3
+2449 c 361 3
+2455 7 363 3
+245c 21 365 3
+247d 4a 368 3
+24c7 9 370 3
+24d0 1a 371 3
+24ea 4b 372 3
+2535 4 373 3
+2539 5 371 3
+253e 29 374 3
+2567 2d 376 3
+2594 4b 378 3
+25df 4 379 3
+25e3 a 382 3
+25ed b 383 3
+FUNC 25f8 c9 0 -[DumpSymbols loadSymbolInfo:offset:]
+25f8 13 391 3
+260b 2b 392 3
+2636 2a 393 3
+2660 2d 395 3
+268d 2e 398 3
+26bb 6 399 3
+26c1 1 399 3
+FUNC 26c2 2be 0 -[DumpSymbols loadSTABSSymbolInfo:offset:]
+26c2 16 537 3
+26d8 9 538 3
+26e1 10 539 3
+26f1 2e 540 3
+271f 9 542 3
+2728 22 543 3
+274a 4 544 3
+274e a 546 3
+2758 3c 547 3
+2794 c 549 3
+27a0 e 550 3
+27ae 6 551 3
+27b4 25 552 3
+27d9 25 553 3
+27fe 25 554 3
+2823 c 555 3
+282f c 556 3
+283b c 559 3
+2847 23 562 3
+286a a 563 3
+2874 a 564 3
+287e 2e 565 3
+28ac 39 566 3
+28e5 2e 570 3
+2913 4 571 3
+2917 17 559 3
+292e 25 575 3
+2953 9 576 3
+295c 17 549 3
+2973 4 579 3
+2977 9 580 3
+FUNC 2980 28a 0 -[DumpSymbols loadSymbolInfo64:offset:]
+2980 16 583 3
+2996 9 585 3
+299f 10 586 3
+29af 2e 587 3
+29dd 9 589 3
+29e6 22 590 3
+2a08 4 591 3
+2a0c c 593 3
+2a18 e 594 3
+2a26 6 595 3
+2a2c 25 596 3
+2a51 25 597 3
+2a76 25 598 3
+2a9b 9 599 3
+2aa4 c 600 3
+2ab0 c 603 3
+2abc 17 604 3
+2ad3 23 609 3
+2af6 a 610 3
+2b00 a 611 3
+2b0a 2e 612 3
+2b38 37 613 3
+2b6f 2e 615 3
+2b9d 4 616 3
+2ba1 17 603 3
+2bb8 25 620 3
+2bdd 9 621 3
+2be6 17 593 3
+2bfd 4 624 3
+2c01 9 625 3
+FUNC 2c0a 199 0 -[DumpSymbols loadSymbolInfoForArchitecture]
+2c0a 13 628 3
+2c1d 41 630 3
+2c5e 2b 631 3
+2c89 1a 632 3
+2ca3 40 634 3
+2ce3 40 635 3
+2d23 5f 637 3
+2d82 17 639 3
+2d99 4 640 3
+2d9d 6 641 3
+2da3 1 641 3
+FUNC 2da4 3e5 0 -[DumpSymbols loadHeader:offset:]
+2da4 18 728 3
+2dbc 9 729 3
+2dc5 10 730 3
+2dd5 2e 731 3
+2e03 9 733 3
+2e0c 2b 734 3
+2e37 1e 736 3
+2e55 c 738 3
+2e61 e 739 3
+2e6f 6 740 3
+2e75 50 742 3
+2ec5 2e 743 3
+2ef3 2e 744 3
+2f21 2e 745 3
+2f4f 20 746 3
+2f6f 1b7 755 3
+3126 9 757 3
+312f 25 761 3
+3154 9 762 3
+315d 17 738 3
+3174 a 765 3
+317e b 766 3
+3189 1 766 3
+FUNC 318a 41d 0 -[DumpSymbols loadHeader64:offset:]
+318a 18 769 3
+31a2 9 771 3
+31ab 10 772 3
+31bb 2e 773 3
+31e9 9 775 3
+31f2 c 777 3
+31fe 2b 778 3
+3229 e 779 3
+3237 6 780 3
+323d 50 781 3
+328d 49 782 3
+32d6 49 783 3
+331f 2e 784 3
+334d 9 785 3
+3356 29 786 3
+337f 1c5 794 3
+3544 9 795 3
+354d 25 799 3
+3572 9 800 3
+357b 17 777 3
+3592 a 803 3
+359c b 804 3
+35a7 1 804 3
+FUNC 35a8 52a 0 -[DumpSymbols loadModuleInfo]
+35a8 14 807 3
+35bc e 808 3
+35ca 41 810 3
+360b 1a 811 3
+3625 6 812 3
+362b 6 814 3
+3631 17 815 3
+3648 c 816 3
+3654 29 820 3
+367d 29 821 3
+36a6 29 822 3
+36cf 35 824 3
+3704 12 826 3
+3716 17 827 3
+372d c 828 3
+3739 3c 832 3
+3775 a 834 3
+377f 9 836 3
+3788 25 837 3
+37ad c 839 3
+37b9 54 840 3
+380d 57 841 3
+3864 57 842 3
+38bb 57 843 3
+3912 57 844 3
+3969 1c 846 3
+3985 4b 847 3
+39d0 49 849 3
+3a19 13 839 3
+3a2c 6 851 3
+3a32 3c 852 3
+3a6e 3a 854 3
+3aa8 17 857 3
+3abf c 858 3
+3acb 7 859 3
+FUNC 3ad2 b6 0 WriteFormat
+3ad2 10 862 3
+3ae2 6 867 3
+3ae8 24 868 3
+3b0c 27 869 3
+3b33 40 870 3
+3b73 c 873 3
+3b7f 9 874 3
+FUNC 3b88 35 0 -[DumpSymbols availableArchitectures]
+3b88 13 1140 3
+3b9b 1c 1141 3
+3bb7 6 1142 3
+3bbd 1 1142 3
+FUNC 3bbe 1b4 0 -[DumpSymbols setArchitecture:]
+3bbe 13 1158 3
+3bd1 1a 1159 3
+3beb 4 1160 3
+3bef 2a 1162 3
+3c19 9 1163 3
+3c22 2a 1165 3
+3c4c 9 1166 3
+3c55 9 1167 3
+3c5e 2a 1169 3
+3c88 6 1170 3
+3c8e 2a 1172 3
+3cb8 6 1173 3
+3cbe 2a 1175 3
+3ce8 4 1176 3
+3cec 6 1179 3
+3cf2 2c 1180 3
+3d1e 9 1181 3
+3d27 1c 1183 3
+3d43 1f 1184 3
+3d62 a 1187 3
+3d6c 6 1188 3
+FUNC 3d72 14 0 -[DumpSymbols architecture]
+3d72 c 1191 3
+3d7e 6 1192 3
+3d84 2 1193 3
+FUNC 3d86 e7 0 -[DumpSymbols writeSymbolFile:]
+3d86 13 1196 3
+3d99 1a 1197 3
+3db3 48 1200 3
+3dfb 9 1201 3
+3e04 1e 1203 3
+3e22 6 1205 3
+3e28 9 1206 3
+3e31 21 1208 3
+3e52 b 1210 3
+3e5d a 1212 3
+3e67 6 1213 3
+3e6d 1 1213 3
+FUNC 3e6e 65 0 -[MachSection initWithMachSection:andNumber:]
+3e6e 13 1219 3
+3e81 37 1220 3
+3eb8 9 1221 3
+3ec1 9 1222 3
+3eca 3 1225 3
+3ecd 6 1226 3
+3ed3 1 1226 3
+FUNC 3ed4 14 0 -[MachSection sectionPointer]
+3ed4 c 1228 3
+3ee0 6 1229 3
+3ee6 2 1230 3
+FUNC 3ee8 14 0 -[MachSection sectionNumber]
+3ee8 c 1232 3
+3ef4 6 1233 3
+3efa 2 1234 3
+FUNC 3efc 17c 0 -[DumpSymbols processDWARFSourceFileInfo:]
+3efc 14 459 3
+3f10 a 460 3
+3f1a 3c 461 3
+3f56 20 463 3
+3f76 5 464 3
+3f7b 3a 465 3
+3fb5 1d 466 3
+3fd2 3a 467 3
+400c 2a 468 3
+4036 3b 464 3
+4071 7 471 3
+FUNC 4078 1d7 0 DumpFunctionMap(std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >)
+4078 15 82 3
+408d 13 83 3
+40a0 1e 85 3
+40be 42 89 3
+4100 20 90 3
+4120 2b 91 3
+414b 1a 92 3
+4165 23 93 3
+4188 46 96 3
+41ce 46 99 3
+4214 33 83 3
+4247 8 102 3
+424f 1 102 3
+FUNC 4250 3ef 0 -[DumpSymbols processDWARFFunctionInfo:]
+4250 15 473 3
+4265 25 474 3
+428a 1e 476 3
+42a8 a 480 3
+42b2 3c 481 3
+42ee 3d 483 3
+432b 23 485 3
+434e 26 487 3
+4374 6 489 3
+437a 37 490 3
+43b1 2a 491 3
+43db 17 492 3
+43f2 30 496 3
+4422 3d 497 3
+445f 2e 498 3
+448d 30 502 3
+44bd 64 504 3
+4521 34 507 3
+4555 9d 509 3
+45f2 45 474 3
+4637 8 513 3
+463f 1 513 3
+FUNC 4640 1f5 0 -[DumpSymbols processDWARFLineNumberInfo:]
+4640 15 515 3
+4655 25 516 3
+467a 39 520 3
+46b3 26 521 3
+46d9 6 523 3
+46df 37 524 3
+4716 2a 525 3
+4740 17 526 3
+4757 30 529 3
+4787 61 531 3
+47e8 45 516 3
+482d 8 534 3
+4835 1 534 3
+FUNC 4836 10f 0 -[DumpSymbols dealloc]
+4836 13 1145 3
+4849 1c 1146 3
+4865 1c 1147 3
+4881 1c 1148 3
+489d 1c 1149 3
+48b9 1c 1150 3
+48d5 1c 1151 3
+48f1 25 1152 3
+4916 29 1154 3
+493f 6 1155 3
+4945 1 1155 3
+FUNC 4946 512 0 -[DumpSymbols loadDWARFSymbolInfo:offset:]
+4946 17 402 3
+495d 9 405 3
+4966 10 406 3
+4976 2b 408 3
+49a1 38 409 3
+49d9 3a 410 3
+4a13 2e 411 3
+4a41 31 416 3
+4a72 e 418 3
+4a80 24 420 3
+4aa4 5 422 3
+4aa9 b 424 3
+4ab4 b 425 3
+4abf e 426 3
+4acd 2b 427 3
+4af8 2b 428 3
+4b23 2c 431 3
+4b4f 52 439 3
+4ba1 34 444 3
+4bd5 1a 446 3
+4bef 21 451 3
+4c10 1e 452 3
+4c2e 21 453 3
+4c4f 40 422 3
+4c8f 6 453 3
+4c95 170 422 3
+4e05 43 456 3
+4e48 10 457 3
+FUNC 4e58 4fd 0 -[DumpSymbols generateSectionDictionary:]
+4e58 18 663 3
+4e70 10 665 3
+4e80 2e 666 3
+4eae 9 668 3
+4eb7 2b 669 3
+4ee2 7 670 3
+4ee9 2e 672 3
+4f17 d 676 3
+4f24 32 678 3
+4f56 29 680 3
+4f7f a 684 3
+4f89 3c 685 3
+4fc5 31 688 3
+4ff6 5d 689 3
+5053 26 692 3
+5079 21 694 3
+509a c 698 3
+50a6 e 699 3
+50b4 6 700 3
+50ba 9 701 3
+50c3 2e 702 3
+50f1 c 704 3
+50fd 3c 706 3
+5139 66 709 3
+519f 1c 712 3
+51bb fb 714 3
+52b6 6 717 3
+52bc 5 718 3
+52c1 19 704 3
+52da 25 714 3
+52ff 2e 722 3
+532d 9 723 3
+5336 17 698 3
+534d 8 725 3
+5355 1 725 3
+FUNC 5356 24a 0 -[DumpSymbols getSectionMapForArchitecture:]
+5356 14 643 3
+536a 43 645 3
+53ad 1a 648 3
+53c7 1c 645 3
+53e3 18 648 3
+53fb 40 650 3
+543b 20 651 3
+545b 17 652 3
+5472 16 651 3
+5488 cb 652 3
+5553 11 654 3
+5564 32 657 3
+5596 a 658 3
+FUNC 55a0 3fe 0 -[DumpSymbols initWithContentsOfFile:]
+55a0 14 1056 3
+55b4 3b 1057 3
+55ef 44 1059 3
+5633 17 1060 3
+564a c 1061 3
+5656 1f 1064 3
+5675 2b 1067 3
+56a0 a 1069 3
+56aa 35 1083 3
+56df 2 1087 3
+56e1 1a 1088 3
+56fb 3d 1087 3
+5738 33 1092 3
+576b 6 1094 3
+5771 e 1095 3
+577f 17 1096 3
+5796 c 1097 3
+57a2 1c 1101 3
+57be 1f 1103 3
+57dd 18 1104 3
+57f5 23 1107 3
+5818 25 1109 3
+583d 1c 1107 3
+5859 17 1110 3
+5870 c 1111 3
+587c 2a 1115 3
+58a6 8 1116 3
+58ae a 1118 3
+58b8 9 1119 3
+58c1 d 1122 3
+58ce 29 1124 3
+58f7 20 1126 3
+5917 20 1128 3
+5937 57 1132 3
+598e 9 1136 3
+5997 7 1137 3
+FUNC 599e d74 0 -[DumpSymbols outputSymbolFile:]
+599e 18 877 3
+59b6 2e 879 3
+59e4 30 880 3
+5a14 5d 882 3
+5a71 30 883 3
+5aa1 5d 885 3
+5afe 2e 888 3
+5b2c 38 891 3
+5b64 46 892 3
+5baa 26 893 3
+5bd0 20 895 3
+5bf0 20 904 3
+5c10 30 898 3
+5c40 f 899 3
+5c4f 1e 904 3
+5c6d 17 907 3
+5c84 17 908 3
+5c9b 44 911 3
+5cdf 44 914 3
+5d23 a 917 3
+5d2d 36 921 3
+5d63 30 923 3
+5d93 9 18 4
+5d9c 9 19 4
+5da5 c 20 4
+5db1 56 923 3
+5e07 74 925 3
+5e7b f 927 3
+5e8a 44 932 3
+5ece 20 933 3
+5eee c 934 3
+5efa 4e 935 3
+5f48 41 936 3
+5f89 f 937 3
+5f98 14 934 3
+5fac 7 941 3
+5fb3 14 942 3
+5fc7 14 943 3
+5fdb 1d 946 3
+5ff8 c 948 3
+6004 24 949 3
+6028 29 950 3
+6051 9 953 3
+605a 28 954 3
+6082 2e 955 3
+60b0 1e 957 3
+60ce 7 959 3
+60d5 26 962 3
+60fb 2a 963 3
+6125 2a 964 3
+614f 6 966 3
+6155 2a 967 3
+617f e 971 3
+618d 43 972 3
+61d0 4c 974 3
+621c 8 975 3
+6224 2e 979 3
+6252 2e 982 3
+6280 2e 985 3
+62ae 2e 988 3
+62dc 2e 991 3
+630a 2e 994 3
+6338 2e 997 3
+6366 2e 1000 3
+6394 54 1004 3
+63e8 c 1005 3
+63f4 e 1007 3
+6402 27 1008 3
+6429 8 1009 3
+6431 34 1010 3
+6465 24 1012 3
+6489 2 1013 3
+648b 2a 1017 3
+64b5 a 1019 3
+64bf 14 1020 3
+64d3 1d 1021 3
+64f0 a 1025 3
+64fa 32 1026 3
+652c 33 1028 3
+655f c 1029 3
+656b 55 1034 3
+65c0 f 1036 3
+65cf 16 1040 3
+65e5 61 1041 3
+6646 f 1043 3
+6655 47 1046 3
+669c c 1048 3
+66a8 11 948 3
+66b9 4e 1052 3
+6707 b 1053 3
+FUNC 6712 11 0 operator new(unsigned long, void*)
+6712 c 94 5
+671e 5 94 5
+6723 1 94 5
+FUNC 6724 e 0 operator delete(void*, void*)
+6724 c 98 5
+6730 2 98 5
+673e 7 76 6
+6745 2 77 6
+6747 1a 78 6
+6761 d 77 6
+676e 3 79 6
+6771 2 80 6
+6773 1 80 6
+6780 d 95 6
+678d 1 95 6
+678e 13 127 74
+67a1 2a 127 74
+67cb 1 127 74
+67cc 13 127 74
+67df 2a 127 74
+6809 1 127 74
+680a 13 127 74
+681d 2a 127 74
+6847 1 127 74
+FUNC 6848 e 0 dwarf2reader::LineInfoHandler::DefineDir(std::string const&, unsigned int)
+6848 c 131 7
+6854 2 131 74
+FUNC 6856 26 0 dwarf2reader::LineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long)
+6856 24 142 7
+687a 2 142 74
+FUNC 687c 1a 0 dwarf2reader::LineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int)
+687c 18 150 7
+6894 2 150 74
+6896 12 299 74
+68a8 12 299 74
+68ba 13 301 74
+68cd 2a 301 74
+68f7 1 301 74
+68f8 13 301 74
+690b 2a 301 74
+6935 1 301 74
+6936 13 301 74
+6949 2a 301 74
+6973 1 301 74
+FUNC 6974 44 0 dwarf2reader::Dwarf2Handler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char)
+6974 39 308 7
+69ad b 308 74
+FUNC 69b8 1f 0 dwarf2reader::Dwarf2Handler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+69b8 18 314 7
+69d0 7 314 74
+69d7 1 314 74
+FUNC 69d8 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long)
+69d8 24 323 7
+69fc 2 323 74
+FUNC 69fe 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeSigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, long long)
+69fe 24 332 7
+6a22 2 332 74
+FUNC 6a24 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeBuffer(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, char const*, unsigned long long)
+6a24 24 345 7
+6a48 2 345 74
+FUNC 6a4a 1a 0 dwarf2reader::Dwarf2Handler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&)
+6a4a 18 354 7
+6a62 2 354 74
+FUNC 6a64 1a 0 dwarf2reader::Dwarf2Handler::EndDIE(unsigned long long)
+6a64 18 360 7
+6a7c 2 360 74
+6a7e c 44 8
+6a8a 2 44 8
+6a8c 13 55 32
+6a9f 35 55 32
+6ad4 13 91 32
+6ae7 73 96 32
+6b5a 13 98 32
+6b6d 35 98 32
+6bae 1a 75 3
+6bc8 2 76 3
+FUNC 6bca 20 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator!=(std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const&) const
+6bca c 287 10
+6bd6 14 288 40
+FUNC 6bea 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator->() const
+6bea c 249 10
+6bf6 a 250 40
+6c0c 7 614 72
+6c13 1 614 72
+6c14 c 241 40
+6c20 c 242 40
+FUNC 6c2c 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator*() const
+6c2c c 245 11
+6c38 a 246 40
+6c42 c 241 40
+6c4e c 242 40
+FUNC 6c5a 20 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator!=(std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const&) const
+6c5a c 287 11
+6c66 14 288 40
+FUNC 6c7a 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator->() const
+6c7a c 249 11
+6c86 a 250 40
+6c90 c 185 34
+6c9c 18 186 34
+6cc0 14 204 34
+6cd4 c 69 70
+6ce0 d 69 70
+6ced 1 69 70
+6cee c 89 70
+6cfa 20 90 70
+6d1a c 69 70
+6d26 d 69 70
+6d33 1 69 70
+6d34 c 69 70
+6d40 d 69 70
+6d4d 1 69 70
+FUNC 6d4e 25 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator++()
+6d4e c 253 13
+6d5a 14 255 40
+6d6e 5 256 40
+6d73 1 256 40
+FUNC 6d74 25 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator++()
+6d74 c 253 13
+6d80 14 255 40
+6d94 5 256 40
+6d99 1 256 40
+FUNC 6d9a 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_begin()
+6d9a c 461 13
+6da6 8 462 40
+FUNC 6dae 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_begin()
+6dae c 461 13
+6dba 8 462 40
+6dc2 c 65 68
+6dce 2 65 68
+6dd0 c 72 68
+6ddc 2 72 68
+6dde c 97 69
+6dea d 97 69
+6df7 1 97 69
+6df8 c 105 69
+6e04 d 105 69
+6e11 1 105 69
+6e12 c 105 69
+6e1e d 105 69
+6e2b 1 105 69
+6e2c c 67 68
+6e38 2 67 68
+6e3a c 99 69
+6e46 14 100 69
+6e5a c 99 69
+6e66 14 100 69
+FUNC 6e7a 2b 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::get_allocator() const
+6e7a 10 93 16
+6e8a 1b 94 71
+6ea5 1 94 71
+6ea6 c 65 68
+6eb2 2 65 68
+6eb4 c 72 68
+6ec0 2 72 68
+6ec2 c 97 69
+6ece d 97 69
+6edb 1 97 69
+6edc c 105 69
+6ee8 d 105 69
+6ef5 1 105 69
+6ef6 c 105 69
+6f02 d 105 69
+6f0f 1 105 69
+6f10 c 67 68
+6f1c 2 67 68
+6f1e c 99 69
+6f2a 14 100 69
+6f3e c 99 69
+6f4a 14 100 69
+FUNC 6f5e 2b 0 std::_Vector_base<std::string, std::allocator<std::string> >::get_allocator() const
+6f5e 10 93 16
+6f6e 1b 94 71
+6f89 1 94 71
+6f8a c 603 72
+6f96 c 603 72
+FUNC 6fa2 23 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::begin()
+6fa2 c 333 16
+6fae 17 334 71
+6fc5 1 334 71
+FUNC 6fc6 26 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::end()
+6fc6 c 351 16
+6fd2 1a 352 71
+6ff8 5 666 72
+6ffd 1 666 72
+6ffe c 608 72
+700a 14 609 72
+702a 5 666 72
+702f 1 666 72
+FUNC 7030 35 0 bool __gnu_cxx::operator!=<dwarf2reader::SourceFileInfo const*, dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo const*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&)
+7030 d 693 16
+703d 28 694 72
+7065 1 694 72
+7066 c 603 72
+7072 c 603 72
+708a 27 629 72
+70b1 1 629 72
+70b2 c 84 70
+70be 1f 85 70
+70dd 1 85 70
+FUNC 70de 32 0 std::pair<std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> std::make_pair<std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*>(std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*)
+70de 10 144 16
+70ee 22 145 70
+711c a 190 34
+7132 d 194 34
+713f 1 194 34
+7140 c 84 70
+714c 17 85 70
+7163 1 85 70
+FUNC 7164 2d 0 std::pair<char const*, unsigned long> std::make_pair<char const*, unsigned long>(char const*, unsigned long)
+7164 c 144 16
+7170 21 145 70
+7191 1 145 70
+7192 c 84 70
+719e 1d 85 70
+71bb 1 85 70
+FUNC 71bc 30 0 std::pair<char*, std::pair<char const*, unsigned long> > std::make_pair<char*, std::pair<char const*, unsigned long> >(char*, std::pair<char const*, unsigned long>)
+71bc 10 144 16
+71cc 20 145 70
+71ec c 89 70
+71f8 20 90 70
+7218 d 89 70
+7225 70 90 70
+7295 1 90 70
+FUNC 7296 12 0 std::iterator_traits<unsigned long const*>::iterator_category std::__iterator_category<unsigned long const*>(unsigned long const* const&)
+7296 c 164 17
+72a2 6 165 17
+FUNC 72a8 1d 0 std::iterator_traits<unsigned long const*>::difference_type std::__distance<unsigned long const*>(unsigned long const*, unsigned long const*, std::random_access_iterator_tag)
+72a8 c 92 18
+72b4 11 97 18
+72c5 1 97 18
+FUNC 72c6 33 0 std::iterator_traits<unsigned long const*>::difference_type std::distance<unsigned long const*>(unsigned long const*, unsigned long const*)
+72c6 c 114 18
+72d2 27 118 18
+72f9 1 118 18
+FUNC 72fa 20 0 void std::__advance<unsigned long const*, int>(unsigned long const*&, int, std::random_access_iterator_tag)
+72fa c 150 18
+7306 14 155 18
+FUNC 731a 33 0 void std::advance<unsigned long const*, int>(unsigned long const*&, int)
+731a c 172 18
+7326 27 175 18
+734d 1 175 18
+FUNC 734e 7a 0 unsigned long const* std::lower_bound<unsigned long const*, unsigned long>(unsigned long const*, unsigned long const*, unsigned long const&)
+734e c 2625 19
+735a 15 2642 19
+736f 2 2646 19
+7371 8 2648 19
+7379 6 2649 19
+737f 12 2650 19
+7391 e 2651 19
+739f 6 2653 19
+73a5 4 2654 19
+73a9 e 2655 19
+73b7 6 2658 19
+73bd 6 2646 19
+73c3 5 2660 19
+73db b 227 34
+73e6 e 228 34
+73f4 1c 229 34
+7410 20 230 34
+7430 6 231 34
+7436 c 72 68
+7442 2 72 68
+7444 c 105 69
+7450 d 105 69
+745d 1 105 69
+745e c 105 69
+746a d 105 69
+7477 1 105 69
+7478 c 80 71
+7484 d 80 71
+7491 1 80 71
+7492 c 67 68
+749e 2 67 68
+74a0 c 99 69
+74ac 14 100 69
+FUNC 74c0 2b 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::get_allocator() const
+74c0 10 93 19
+74d0 1b 94 71
+74eb 1 94 71
+74ec c 238 40
+74f8 a 239 40
+FUNC 7502 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin() const
+7502 c 585 19
+750e 1a 588 40
+FUNC 7528 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin() const
+7528 c 243 20
+7534 d 244 45
+7541 1 244 45
+FUNC 7542 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end() const
+7542 c 596 20
+754e 1a 597 40
+FUNC 7568 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end() const
+7568 c 260 20
+7574 d 261 45
+7581 1 261 45
+7582 c 65 68
+758e 2 65 68
+7590 c 72 68
+759c 2 72 68
+759e c 97 69
+75aa d 97 69
+75b7 1 97 69
+75b8 c 105 69
+75c4 d 105 69
+75d1 1 105 69
+75d2 c 72 68
+75de 2 72 68
+75e0 c 105 69
+75ec d 105 69
+75f9 1 105 69
+75fa c 397 40
+7606 d 397 40
+7613 1 397 40
+7614 c 105 69
+7620 d 105 69
+762d 1 105 69
+FUNC 762e 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_right(std::_Rb_tree_node_base*)
+762e c 496 20
+763a 8 497 40
+FUNC 7642 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_left(std::_Rb_tree_node_base*)
+7642 c 488 20
+764e 8 489 40
+7656 c 65 68
+7662 2 65 68
+7664 c 72 68
+7670 2 72 68
+7672 c 97 69
+767e d 97 69
+768b 1 97 69
+768c c 105 69
+7698 d 105 69
+76a5 1 105 69
+76a6 c 72 68
+76b2 2 72 68
+76b4 c 105 69
+76c0 d 105 69
+76cd 1 105 69
+76ce c 397 40
+76da d 397 40
+76e7 1 397 40
+76e8 c 105 69
+76f4 d 105 69
+7701 1 105 69
+FUNC 7702 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_right(std::_Rb_tree_node_base*)
+7702 c 496 20
+770e 8 497 40
+FUNC 7716 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_left(std::_Rb_tree_node_base*)
+7716 c 488 20
+7722 8 489 40
+772a c 84 71
+7736 2f 85 71
+7765 2 86 71
+7767 1 86 71
+7768 c 80 71
+7774 d 80 71
+7781 1 80 71
+7782 c 96 71
+778e 12 97 71
+77a0 2 98 71
+77a2 c 84 71
+77ae 2f 85 71
+77dd 2 86 71
+77df 1 86 71
+77e0 c 80 71
+77ec d 80 71
+77f9 1 80 71
+77fa c 96 71
+7806 12 97 71
+7818 2 98 71
+7826 d 107 68
+7833 1 107 68
+FUNC 7834 2e 0 void std::_Destroy<std::string*, std::allocator<std::string> >(std::string*, std::string*, std::allocator<std::string>)
+7834 c 171 21
+7840 2 173 73
+7842 12 174 73
+7854 c 173 73
+7860 2 174 73
+7862 c 167 40
+786e a 168 40
+FUNC 7878 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin()
+7878 c 581 21
+7884 1a 582 40
+FUNC 789e 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin()
+789e c 234 21
+78aa d 235 45
+78b7 1 235 45
+FUNC 78b8 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end()
+78b8 c 592 21
+78c4 1a 593 40
+FUNC 78de 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end()
+78de c 251 21
+78ea d 252 45
+78f7 1 252 45
+78f8 c 167 40
+7904 a 168 40
+FUNC 790e 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::begin()
+790e c 581 21
+791a 1a 582 40
+FUNC 7934 19 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::begin()
+7934 c 234 21
+7940 d 235 45
+794d 1 235 45
+FUNC 794e 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::end()
+794e c 592 21
+795a 1a 593 40
+FUNC 7974 19 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::end()
+7974 c 251 21
+7980 d 252 45
+798d 1 252 45
+FUNC 798e 11 0 std::_Select1st<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >::operator()(std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*>&) const
+798e c 546 22
+799a 5 547 41
+799f 1 547 41
+79a0 c 128 34
+79ac 13 129 34
+79bf 1 129 34
+79cc 22 396 34
+79fa d 199 42
+7a07 1 199 42
+7a08 c 65 68
+7a14 2 65 68
+7a16 c 72 68
+7a22 2 72 68
+7a24 c 97 69
+7a30 d 97 69
+7a3d 1 97 69
+7a3e c 105 69
+7a4a d 105 69
+7a57 1 105 69
+7a58 c 65 68
+7a64 2 65 68
+7a66 c 72 68
+7a72 2 72 68
+7a74 c 105 69
+7a80 d 105 69
+7a8d 1 105 69
+7a8e c 97 69
+7a9a d 97 69
+7aa7 1 97 69
+7aa8 c 72 68
+7ab4 2 72 68
+7ab6 c 105 69
+7ac2 d 105 69
+7acf 1 105 69
+7adc d 94 68
+7ae9 1 94 68
+FUNC 7aea 2f 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_deallocate(dwarf2reader::CompilationUnit::Abbrev*, unsigned long)
+7aea c 120 23
+7af6 6 122 71
+7afc 1d 123 71
+7b19 1 123 71
+7b1a c 108 71
+7b26 43 109 71
+7b69 1 109 71
+7b6a c 65 68
+7b76 2 65 68
+7b78 c 103 69
+7b84 d 103 69
+7b91 1 103 69
+7b92 c 65 68
+7b9e 2 65 68
+7ba0 c 103 69
+7bac d 103 69
+7bb9 1 103 69
+7bc6 d 94 68
+7bd3 1 94 68
+FUNC 7bd4 2f 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_deallocate(dwarf2reader::SourceFileInfo*, unsigned long)
+7bd4 c 120 23
+7be0 6 122 71
+7be6 1d 123 71
+7c03 1 123 71
+7c04 c 108 71
+7c10 43 109 71
+7c53 1 109 71
+7c54 c 188 71
+7c60 12 189 71
+7c72 2 190 71
+7c74 c 35 32
+7c80 d 35 32
+7c8d 1 35 32
+7c9a d 107 68
+7ca7 1 107 68
+FUNC 7ca8 2e 0 void std::_Destroy<dwarf2reader::SourceFileInfo*, std::allocator<dwarf2reader::SourceFileInfo> >(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, std::allocator<dwarf2reader::SourceFileInfo>)
+7ca8 c 171 23
+7cb4 2 173 73
+7cb6 12 174 73
+7cc8 c 173 73
+7cd4 2 174 73
+7cd6 d 272 71
+7ce3 8c 273 71
+7d6f 1 273 71
+7d7c d 94 68
+7d89 1 94 68
+FUNC 7d8a 2f 0 std::_Vector_base<std::string, std::allocator<std::string> >::_M_deallocate(std::string*, unsigned long)
+7d8a c 120 23
+7d96 6 122 71
+7d9c 1d 123 71
+7db9 1 123 71
+7dba c 108 71
+7dc6 3d 109 71
+7e03 1 109 71
+7e04 c 188 71
+7e10 12 189 71
+7e22 2 190 71
+7e24 d 272 71
+7e31 8c 273 71
+7ebd 1 273 71
+7eca 2b 596 34
+7ef5 1 596 34
+7f02 7 614 72
+7f09 1 614 72
+7f0a c 65 68
+7f16 2 65 68
+7f18 c 72 68
+7f24 2 72 68
+7f26 c 103 69
+7f32 d 103 69
+7f3f 1 103 69
+7f40 c 105 69
+7f4c d 105 69
+7f59 1 105 69
+7f5a c 65 68
+7f66 2 65 68
+7f68 c 72 68
+7f74 2 72 68
+7f76 c 103 69
+7f82 d 103 69
+7f8f 1 103 69
+7f90 c 105 69
+7f9c d 105 69
+7fa9 1 105 69
+7faa c 105 69
+7fb6 d 105 69
+7fc3 1 105 69
+7fd0 d 575 34
+7fdd 1 575 34
+7fea d 575 34
+7ff7 1 575 34
+FUNC 7ff8 11 0 std::_Select1st<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >::operator()(std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> const&) const
+7ff8 c 550 23
+8004 5 551 41
+8009 1 551 41
+8016 2f 600 34
+8045 1 600 34
+8046 c 84 70
+8052 1e 85 70
+FUNC 8070 11 0 std::_Select1st<std::pair<std::string const, std::pair<char const*, unsigned long long> > >::operator()(std::pair<std::string const, std::pair<char const*, unsigned long long> >&) const
+8070 c 546 23
+807c 5 547 41
+8081 1 547 41
+FUNC 8082 11 0 std::_Select1st<std::pair<std::string const, std::pair<char const*, unsigned long long> > >::operator()(std::pair<std::string const, std::pair<char const*, unsigned long long> > const&) const
+8082 c 550 23
+808e 5 551 41
+8093 1 551 41
+8094 c 128 34
+80a0 13 129 34
+80b3 1 129 34
+80b4 c 84 70
+80c0 1e 85 70
+80de c 65 68
+80ea 2 65 68
+80ec c 103 69
+80f8 d 103 69
+8105 1 103 69
+8106 c 65 68
+8112 2 65 68
+8114 c 72 68
+8120 2 72 68
+8122 c 105 69
+812e d 105 69
+813b 1 105 69
+813c c 103 69
+8148 d 103 69
+8155 1 103 69
+8156 c 105 69
+8162 d 105 69
+816f 1 105 69
+8170 c 80 71
+817c d 80 71
+8189 1 80 71
+818a c 67 68
+8196 2 67 68
+8198 c 99 69
+81a4 14 100 69
+FUNC 81b8 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::get_allocator() const
+81b8 10 93 23
+81c8 1b 94 71
+81e3 1 94 71
+81e4 c 99 69
+81f0 14 100 69
+8210 2 107 68
+FUNC 8212 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+8212 c 171 23
+821e 2 173 73
+8220 12 174 73
+8232 c 173 73
+823e 2 174 73
+824c d 107 68
+8259 1 107 68
+825a c 67 68
+8266 2 67 68
+8268 c 99 69
+8274 14 100 69
+8288 c 403 40
+8294 1c 404 40
+82b0 a 406 40
+82ba a 407 40
+82c4 c 408 40
+82d0 e 409 40
+82de c 553 40
+82ea 36 554 40
+8320 2 555 40
+8322 c 103 69
+832e d 103 69
+833b 1 103 69
+FUNC 833c 2b 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::get_allocator() const
+833c 10 350 23
+834c 1b 351 40
+8367 1 351 40
+8368 c 69 70
+8374 2 69 70
+8382 d 107 68
+838f 1 107 68
+839c d 94 68
+83a9 1 94 68
+FUNC 83aa 2a 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_put_node(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+83aa c 359 23
+83b6 1e 360 40
+FUNC 83d4 59 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::destroy_node(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+83d4 d 387 23
+83e1 35 389 40
+8416 17 390 40
+842d 1 390 40
+FUNC 842e 56 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+842e c 1051 23
+843a 2 1054 40
+843c 1a 1056 40
+8456 e 1057 40
+8464 12 1058 40
+8476 6 1059 40
+847c 6 1054 40
+8482 2 1059 40
+8484 d 569 40
+8491 58 570 40
+84e9 1 570 40
+84ea c 147 45
+84f6 31 148 45
+8527 1 148 45
+8528 c 92 45
+8534 d 92 45
+8541 1 92 45
+8542 c 67 68
+854e 2 67 68
+8550 c 99 69
+855c 14 100 69
+8570 c 403 40
+857c 1c 404 40
+8598 a 406 40
+85a2 a 407 40
+85ac c 408 40
+85b8 e 409 40
+85c6 c 553 40
+85d2 36 554 40
+8608 2 555 40
+860a c 103 69
+8616 d 103 69
+8623 1 103 69
+FUNC 8624 2b 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::get_allocator() const
+8624 10 350 23
+8634 1b 351 40
+864f 1 351 40
+8650 c 69 70
+865c d 69 70
+8669 1 69 70
+866a c 69 70
+8676 30 69 70
+86b2 d 107 68
+86bf 1 107 68
+86cc d 94 68
+86d9 1 94 68
+FUNC 86da 2a 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_put_node(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+86da c 359 23
+86e6 1e 360 40
+FUNC 8704 59 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::destroy_node(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+8704 d 387 23
+8711 35 389 40
+8746 17 390 40
+875d 1 390 40
+FUNC 875e 56 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+875e c 1051 23
+876a 2 1054 40
+876c 1a 1056 40
+8786 e 1057 40
+8794 12 1058 40
+87a6 6 1059 40
+87ac 6 1054 40
+87b2 2 1059 40
+87b4 d 569 40
+87c1 58 570 40
+8819 1 570 40
+881a c 147 45
+8826 31 148 45
+8857 1 148 45
+8858 c 92 45
+8864 d 92 45
+8871 1 92 45
+8872 c 603 72
+887e c 603 72
+FUNC 888a 23 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::begin()
+888a c 333 23
+8896 17 334 71
+88ad 1 334 71
+88ba 2a 654 72
+FUNC 88e4 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::operator[](unsigned long)
+88e4 c 494 23
+88f0 36 495 71
+FUNC 8926 26 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::end()
+8926 c 351 23
+8932 1a 352 71
+FUNC 894c 28 0 bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+894c c 2115 24
+8958 1c 2116 37
+FUNC 8974 23 0 std::equal_to<std::string>::operator()(std::string const&, std::string const&) const
+8974 c 199 24
+8980 17 200 41
+8997 1 200 41
+8998 c 80 71
+89a4 d 80 71
+89b1 1 80 71
+89b2 c 67 68
+89be 2 67 68
+89c0 c 99 69
+89cc 14 100 69
+FUNC 89e0 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::get_allocator() const
+89e0 10 93 24
+89f0 1b 94 71
+8a0b 1 94 71
+8a0c c 99 69
+8a18 14 100 69
+8a2c c 84 71
+8a38 2f 85 71
+8a67 2 86 71
+8a69 1 86 71
+8a6a c 96 71
+8a76 12 97 71
+8a88 2 98 71
+8a96 2 107 68
+FUNC 8a98 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+8a98 c 171 24
+8aa4 2 173 73
+8aa6 12 174 73
+8ab8 c 173 73
+8ac4 2 174 73
+FUNC 8ac6 13 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::max_size() const
+8ac6 c 407 24
+8ad2 7 408 71
+8ad9 1 408 71
+8ada c 603 72
+8ae6 c 603 72
+FUNC 8af2 26 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::end()
+8af2 c 351 24
+8afe 1a 352 71
+FUNC 8b18 23 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::begin()
+8b18 c 333 24
+8b24 17 334 71
+8b3b 1 334 71
+8b48 2a 654 72
+8b7e 7 614 72
+8b85 1 614 72
+FUNC 8b86 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::operator[](unsigned long)
+8b86 c 494 24
+8b92 36 495 71
+8bd4 d 107 68
+8be1 1 107 68
+FUNC 8be2 28 0 void std::swap<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**&, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**&)
+8be2 c 92 25
+8bee 8 97 61
+8bf6 a 98 61
+8c00 a 99 61
+FUNC 8c0a 50 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >&)
+8c0a c 733 25
+8c16 12 735 71
+8c28 18 736 71
+8c40 1a 737 71
+8c66 2b 596 34
+8c91 1 596 34
+8c9e 2f 600 34
+8ccd 1 600 34
+FUNC 8cce 28 0 void std::swap<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**&, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**&)
+8cce c 92 25
+8cda 8 97 61
+8ce2 a 98 61
+8cec a 99 61
+FUNC 8cf6 50 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >&)
+8cf6 c 733 25
+8d02 12 735 71
+8d14 18 736 71
+8d2c 1a 737 71
+8d46 c 84 71
+8d52 2f 85 71
+8d81 2 86 71
+8d83 1 86 71
+8d84 c 96 71
+8d90 12 97 71
+8da2 2 98 71
+FUNC 8da4 13 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::max_size() const
+8da4 c 407 25
+8db0 7 408 71
+8db7 1 408 71
+8dc4 d 94 68
+8dd1 1 94 68
+FUNC 8dd2 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long)
+8dd2 c 120 25
+8dde 6 122 71
+8de4 1d 123 71
+8e01 1 123 71
+8e02 c 108 71
+8e0e 3d 109 71
+8e4b 1 109 71
+8e4c c 272 71
+8e58 4b 273 71
+8ea3 1 273 71
+8ea4 c 188 71
+8eb0 12 189 71
+8ec2 2 190 71
+8ec4 c 603 72
+8ed0 c 603 72
+FUNC 8edc 2b 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::begin() const
+8edc c 342 25
+8ee8 1f 343 71
+8f07 1 343 71
+FUNC 8f08 2c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::end() const
+8f08 c 360 25
+8f14 20 361 71
+8f40 5 666 72
+8f45 1 666 72
+8f53 2b 759 72
+FUNC 8f7e 3c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::size() const
+8f7e c 402 25
+8f8a 30 403 71
+8fc6 26 588 34
+8ff8 15 511 34
+900d 79 513 34
+9086 21 517 34
+90a7 1 517 34
+90b4 14 225 42
+90d4 26 592 34
+FUNC 90fa 49 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::capacity() const
+90fa c 449 25
+9106 3d 451 71
+9143 1 451 71
+9144 c 103 69
+9150 d 103 69
+915d 1 103 69
+916e 1b 286 34
+9189 1 286 34
+9196 d 94 68
+91a3 1 94 68
+91b0 1e 301 34
+91db 56 622 34
+9231 17 623 34
+9254 9 1080 34
+925d 1a 1082 34
+9277 2 1083 34
+9279 8 1085 34
+9281 12 1086 34
+9293 6 1087 34
+9299 6 1083 34
+929f 1b 1089 34
+92ba 1d 1080 34
+92d7 c 1091 34
+92e3 1 1091 34
+92e4 d 360 34
+92f1 77 361 34
+9368 c 93 42
+9374 d 93 42
+9381 1 93 42
+9382 c 72 68
+938e 2 72 68
+9390 c 105 69
+939c d 105 69
+93a9 1 105 69
+93aa c 301 66
+93b6 d 301 66
+93c3 1 301 66
+93d0 d 94 68
+93dd 1 94 68
+FUNC 93de 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long)
+93de c 120 26
+93ea 6 122 71
+93f0 1d 123 71
+940d 1 123 71
+940e c 108 71
+941a 3d 109 71
+9457 1 109 71
+9458 c 188 71
+9464 12 189 71
+9476 2 190 71
+9478 c 272 71
+9484 4b 273 71
+94cf 1 273 71
+94d0 c 603 72
+94dc c 603 72
+FUNC 94e8 2b 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::begin() const
+94e8 c 342 26
+94f4 1f 343 71
+9513 1 343 71
+FUNC 9514 2c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::end() const
+9514 c 360 26
+9520 20 361 71
+954c 2d 662 72
+9579 1 662 72
+FUNC 957a 2d 0 unsigned long const& std::max<unsigned long>(unsigned long const&, unsigned long const&)
+957a c 206 26
+9586 e 211 61
+9594 8 212 61
+959c b 213 61
+95a7 1 213 61
+95b4 19 650 72
+95cd 1 650 72
+95da 5 666 72
+95df 1 666 72
+95ed 2b 759 72
+9624 5 666 72
+9629 1 666 72
+9637 2b 759 72
+FUNC 9662 49 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::capacity() const
+9662 c 449 26
+966e 3d 451 71
+96ab 1 451 71
+FUNC 96ac 3c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::size() const
+96ac c 402 26
+96b8 30 403 71
+96f4 26 588 34
+9726 26 592 34
+974c c 103 69
+9758 d 103 69
+9765 1 103 69
+9776 1b 286 34
+9791 1 286 34
+979e d 94 68
+97ab 1 94 68
+97b8 1e 301 34
+97e3 56 622 34
+9839 17 623 34
+985c 9 1080 34
+9865 1a 1082 34
+987f 2 1083 34
+9881 8 1085 34
+9889 12 1086 34
+989b 6 1087 34
+98a1 6 1083 34
+98a7 1b 1089 34
+98c2 1d 1080 34
+98df c 1091 34
+98eb 1 1091 34
+98ec d 360 34
+98f9 77 361 34
+9970 c 69 70
+997c 20 69 70
+99a9 5c 104 68
+9a05 1 104 68
+9a06 c 69 70
+9a12 2c 69 70
+9a4b 5c 104 68
+9aa7 1 104 68
+9ab4 2d 662 72
+9ae1 1 662 72
+9aee 19 650 72
+9b07 1 650 72
+9b14 5 666 72
+9b19 1 666 72
+9b27 2b 759 72
+9b52 c 72 68
+9b5e 2 72 68
+9b60 c 105 69
+9b6c d 105 69
+9b79 1 105 69
+9b7a c 69 70
+9b86 2 69 70
+9b94 d 107 68
+9ba1 1 107 68
+9bae d 94 68
+9bbb 1 94 68
+FUNC 9bbc 2a 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_put_node(std::_List_node<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >*)
+9bbc c 315 26
+9bc8 1e 316 66
+FUNC 9be6 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > > const&)
+9be6 d 699 26
+9bf3 28 700 72
+9c1b 1 700 72
+9c28 d 623 72
+9c35 5 624 72
+FUNC 9c3a 4b 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+9c3a c 539 61
+9c46 8 541 61
+9c4e 2 542 61
+9c50 12 543 61
+9c62 21 542 61
+9c83 2 543 61
+9c85 1 543 61
+FUNC 9c86 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+9c86 c 560 26
+9c92 4 567 61
+9c96 1b 568 61
+9cb1 1 568 61
+FUNC 9cb2 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+9cb2 c 171 26
+9cbe 2 173 73
+9cc0 1a 174 73
+9cda 21 173 73
+9cfb 2 174 73
+9cfd 1 174 73
+9d0a 7 98 68
+9d11 1 98 68
+9d1e 1d 85 68
+9d3b 5 86 68
+9d40 16 88 68
+9d62 1d 297 34
+9d7f 1 297 34
+9d8d e 605 34
+9d9b 9 606 34
+9da4 3c 609 34
+9de0 b 610 34
+9deb 11 609 34
+9dfc b 612 34
+9e07 12 614 34
+9e19 b 615 34
+9e24 13 612 34
+9e37 8 615 34
+9e3f 1 615 34
+9e4d 15 751 34
+9e62 1a 752 34
+9e7c b 754 34
+9e87 49 755 34
+9ed0 3b 756 34
+9f0b 12 754 34
+9f1d 15 758 34
+9f32 8 759 34
+9f3a 1c 760 34
+9f56 f 761 34
+9f65 41 762 34
+9fb2 7 98 68
+9fb9 1 98 68
+9fc6 1d 85 68
+9fe3 5 86 68
+9fe8 17 88 68
+9fff 1 88 68
+a00c 1d 297 34
+a029 1 297 34
+a037 e 605 34
+a045 9 606 34
+a04e 3c 609 34
+a08a b 610 34
+a095 11 609 34
+a0a6 b 612 34
+a0b1 12 614 34
+a0c3 b 615 34
+a0ce 13 612 34
+a0e1 8 615 34
+a0e9 1 615 34
+a0f7 15 751 34
+a10c 1a 752 34
+a126 b 754 34
+a131 49 755 34
+a17a 3b 756 34
+a1b5 12 754 34
+a1c7 15 758 34
+a1dc 8 759 34
+a1e4 1c 760 34
+a200 f 761 34
+a20f 41 762 34
+FUNC a250 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > > const&)
+a250 d 699 26
+a25d 28 700 72
+a285 1 700 72
+a292 d 623 72
+a29f 5 624 72
+FUNC a2a4 4b 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a2a4 c 539 61
+a2b0 8 541 61
+a2b8 2 542 61
+a2ba 12 543 61
+a2cc 21 542 61
+a2ed 2 543 61
+a2ef 1 543 61
+FUNC a2f0 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a2f0 c 560 26
+a2fc 4 567 61
+a300 1b 568 61
+a31b 1 568 61
+FUNC a31c 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+a31c c 171 26
+a328 2 173 73
+a32a 1a 174 73
+a344 21 173 73
+a365 2 174 73
+a367 1 174 73
+a368 c 65 68
+a374 2 65 68
+a376 c 103 69
+a382 d 103 69
+a38f 1 103 69
+FUNC a390 2b 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::get_allocator() const
+a390 10 322 26
+a3a0 1b 324 66
+a3bb 1 324 66
+FUNC a3bc 7b 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_clear()
+a3bc d 69 27
+a3c9 8 72 77
+a3d1 2 73 77
+a3d3 6 75 77
+a3d9 8 76 77
+a3e1 35 77 77
+a416 12 78 77
+a428 a 73 77
+a432 5 78 77
+a437 1 78 77
+a438 c 331 66
+a444 18 332 66
+a45c c 392 66
+a468 d 392 66
+a475 1 392 66
+a476 c 211 74
+a482 10 211 74
+a49e d 107 68
+a4ab 1 107 68
+FUNC a4ac 2e 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+a4ac c 171 27
+a4b8 2 173 73
+a4ba 12 174 73
+a4cc c 173 73
+a4d8 2 174 73
+a4da c 272 71
+a4e6 4b 273 71
+a531 1 273 71
+a532 13 196 74
+a545 10 196 74
+a555 2f 197 74
+a584 1a 198 74
+a59e 13 196 74
+a5b1 10 196 74
+a5c1 2f 197 74
+a5f0 1a 198 74
+a616 7 98 68
+a61d 1 98 68
+a62a 1d 85 68
+a647 5 86 68
+a64c 10 88 68
+FUNC a65c 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_allocate(unsigned long)
+a65c c 116 27
+a668 1e 117 71
+a686 d 100 71
+a693 12 101 71
+a6a5 19 103 71
+a6be b 104 71
+a6c9 3a 105 71
+a703 1 105 71
+a710 7 98 68
+a717 1 98 68
+a724 1d 85 68
+a741 5 86 68
+a746 10 88 68
+FUNC a756 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_allocate(unsigned long)
+a756 c 116 27
+a762 1e 117 71
+a780 d 100 71
+a78d 12 101 71
+a79f 19 103 71
+a7b8 b 104 71
+a7c3 3a 105 71
+a7fd 1 105 71
+a80b 12 424 61
+a81d 2e 425 61
+a84b 13 426 61
+a86a 4 440 61
+a86e 1b 443 61
+a889 1 443 61
+a898 56 482 61
+a8fa 4 514 61
+a8fe 4 515 61
+a902 1b 517 61
+a91d 1 517 61
+a92a 8 616 61
+a932 2 617 61
+a934 8 618 61
+a93c f 617 61
+a94b 5 619 61
+a95c 4 641 61
+a960 1b 642 61
+a97b 1 642 61
+FUNC a97c 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, __true_type)
+a97c c 182 28
+a988 1b 183 79
+a9a3 1 183 79
+FUNC a9a4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a9a4 c 214 28
+a9b0 23 218 79
+a9d3 1 218 79
+FUNC a9d4 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+a9d4 c 308 28
+a9e0 1b 310 79
+a9fb 1 310 79
+a9fc c 200 71
+aa08 19 201 71
+aa21 42 203 71
+aa63 15 205 71
+aa85 11 992 34
+aa96 c 993 34
+aaa2 15 995 34
+aab7 c 996 34
+aac3 4a 998 34
+ab0d f 1001 34
+ab1c 1c 998 34
+ab38 1a 1003 34
+ab52 5 1004 34
+ab57 1f 1007 34
+ab76 1c 1008 34
+ab92 19 1009 34
+abab 19 1010 34
+abc4 1a 1011 34
+abde a 1004 34
+abe8 11 1001 34
+abf9 15 1014 34
+ac0e 13 1028 34
+ac21 b 1016 34
+ac2c 9 1018 34
+ac35 19 1023 34
+ac4e 23 1024 34
+ac71 19 1025 34
+ac8a 1d 1021 34
+aca7 1a 1018 34
+acc1 b 1028 34
+accc b 1016 34
+acd7 1e 1028 34
+acf5 1 1028 34
+ad06 16 438 34
+ad1c 37 439 34
+ad53 1 439 34
+ad64 37 212 42
+ad9b 1 212 42
+ada8 8 616 61
+adb0 2 617 61
+adb2 8 618 61
+adba f 617 61
+adc9 5 619 61
+adda 4 641 61
+adde 1b 642 61
+adf9 1 642 61
+FUNC adfa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, __true_type)
+adfa c 182 28
+ae06 1b 183 79
+ae21 1 183 79
+FUNC ae22 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+ae22 c 214 28
+ae2e 23 218 79
+ae51 1 218 79
+FUNC ae52 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+ae52 c 308 28
+ae5e 1b 310 79
+ae79 1 310 79
+ae7a c 200 71
+ae86 19 201 71
+ae9f 42 203 71
+aee1 15 205 71
+af03 11 992 34
+af14 c 993 34
+af20 15 995 34
+af35 c 996 34
+af41 4a 998 34
+af8b f 1001 34
+af9a 1c 998 34
+afb6 1a 1003 34
+afd0 5 1004 34
+afd5 1f 1007 34
+aff4 1c 1008 34
+b010 19 1009 34
+b029 19 1010 34
+b042 1a 1011 34
+b05c a 1004 34
+b066 11 1001 34
+b077 15 1014 34
+b08c 13 1028 34
+b09f b 1016 34
+b0aa 9 1018 34
+b0b3 19 1023 34
+b0cc 23 1024 34
+b0ef 19 1025 34
+b108 1d 1021 34
+b125 1a 1018 34
+b13f b 1028 34
+b14a b 1016 34
+b155 1e 1028 34
+b173 1 1028 34
+b184 16 438 34
+b19a 37 439 34
+b1d1 1 439 34
+b1e2 37 212 42
+b219 1 212 42
+b227 12 424 61
+b239 2e 425 61
+b267 13 426 61
+b286 4 440 61
+b28a 1b 443 61
+b2a5 1 443 61
+b2b4 56 482 61
+b316 4 514 61
+b31a 4 515 61
+b31e 1b 517 61
+b339 1 517 61
+b346 8 616 61
+b34e 2 617 61
+b350 12 618 61
+b362 16 617 61
+b378 5 619 61
+b37d 1 619 61
+b38a 4 641 61
+b38e 1b 642 61
+b3a9 1 642 61
+FUNC b3aa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, __true_type)
+b3aa c 182 28
+b3b6 1b 183 79
+b3d1 1 183 79
+FUNC b3d2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+b3d2 c 214 28
+b3de 23 218 79
+b401 1 218 79
+FUNC b402 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+b402 c 308 28
+b40e 1b 310 79
+b429 1 310 79
+b436 8 616 61
+b43e 2 617 61
+b440 12 618 61
+b452 16 617 61
+b468 5 619 61
+b46d 1 619 61
+b47a 4 641 61
+b47e 1b 642 61
+b499 1 642 61
+FUNC b49a 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, __true_type)
+b49a c 182 28
+b4a6 1b 183 79
+b4c1 1 183 79
+FUNC b4c2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+b4c2 c 214 28
+b4ce 23 218 79
+b4f1 1 218 79
+FUNC b4f2 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+b4f2 c 308 28
+b4fe 1b 310 79
+b519 1 310 79
+b526 22 300 61
+b548 11 301 61
+b559 1 301 61
+b566 4 315 61
+b56a 1b 317 61
+b585 1 317 61
+b592 1b 326 61
+b5ad 1 326 61
+b5ba 4 384 61
+b5be 4 385 61
+b5c2 1b 387 61
+b5dd 1 387 61
+b5ea 1b 74 79
+b605 1 74 79
+b612 23 113 79
+b635 1 113 79
+b642 1b 254 79
+b65d 1 254 79
+b66a 15 763 71
+b67f 40 766 71
+b6bf 3 768 71
+b6c2 2 773 71
+FUNC b6c4 124 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::reserve(unsigned long)
+b6c4 13 69 29
+b6d7 15 71 78
+b6ec e 72 78
+b6fa 19 73 78
+b713 e 75 78
+b721 28 78 78
+b749 3e 79 78
+b787 30 81 78
+b7b7 8 84 78
+b7bf 11 85 78
+b7d0 18 86 78
+b7f5 33 335 61
+b834 4 384 61
+b838 4 385 61
+b83c 1b 387 61
+b857 1 387 61
+b864 1b 74 79
+b87f 1 74 79
+b88c 23 113 79
+b8af 1 113 79
+b8bc 1b 254 79
+b8d7 1 254 79
+b8e6 56 354 61
+b948 4 384 61
+b94c 4 385 61
+b950 1b 387 61
+b96b 1 387 61
+b978 1b 74 79
+b993 1 74 79
+b9a0 23 113 79
+b9c3 1 113 79
+b9d0 1b 254 79
+b9eb 1 254 79
+FUNC b9ec 46e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+b9ec 14 311 29
+ba00 b 313 78
+ba0b 24 315 78
+ba2f 8 318 78
+ba37 23 319 78
+ba5a 15 320 78
+ba6f c 321 78
+ba7b 51 323 78
+bacc 14 327 78
+bae0 30 328 78
+bb10 35 330 78
+bb45 48 334 78
+bb8d 17 338 78
+bba4 43 339 78
+bbe7 14 342 78
+bbfb 1e 343 78
+bc19 e 348 78
+bc27 1e 349 78
+bc45 e 350 78
+bc53 1d 353 78
+bc70 8 354 78
+bc78 e 355 78
+bc86 27 357 78
+bcad 6 358 78
+bcb3 4d 361 78
+bd00 40 365 78
+bd40 18 367 78
+bd58 4d 368 78
+bda5 3e 379 78
+bde3 30 381 78
+be13 12 384 78
+be25 13 385 78
+be38 22 386 78
+FUNC be5a 2e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+be5a c 657 29
+be66 22 658 71
+be94 15 580 34
+bea9 15 581 34
+bebe 37 582 34
+bef5 c 583 34
+bf01 1 583 34
+bf02 d 335 34
+bf0f 4e 337 34
+bf5d 4d 338 34
+bfaa d 134 42
+bfb7 65 135 42
+c028 22 300 61
+c04a 11 301 61
+c05b 1 301 61
+c068 4 315 61
+c06c 1b 317 61
+c087 1 317 61
+c094 1b 326 61
+c0af 1 326 61
+c0bc 4 384 61
+c0c0 4 385 61
+c0c4 1b 387 61
+c0df 1 387 61
+c0ec 1b 74 79
+c107 1 74 79
+c114 23 113 79
+c137 1 113 79
+c144 1b 254 79
+c15f 1 254 79
+c16c 15 763 71
+c181 40 766 71
+c1c1 3 768 71
+c1c4 2 773 71
+FUNC c1c6 124 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::reserve(unsigned long)
+c1c6 13 69 29
+c1d9 15 71 78
+c1ee e 72 78
+c1fc 19 73 78
+c215 e 75 78
+c223 28 78 78
+c24b 3e 79 78
+c289 30 81 78
+c2b9 8 84 78
+c2c1 11 85 78
+c2d2 18 86 78
+c2f7 33 335 61
+c336 4 384 61
+c33a 4 385 61
+c33e 1b 387 61
+c359 1 387 61
+c366 1b 74 79
+c381 1 74 79
+c38e 23 113 79
+c3b1 1 113 79
+c3be 1b 254 79
+c3d9 1 254 79
+c3e8 56 354 61
+c44a 4 384 61
+c44e 4 385 61
+c452 1b 387 61
+c46d 1 387 61
+c47a 1b 74 79
+c495 1 74 79
+c4a2 23 113 79
+c4c5 1 113 79
+c4d2 1b 254 79
+c4ed 1 254 79
+FUNC c4ee 46e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+c4ee 14 311 29
+c502 b 313 78
+c50d 24 315 78
+c531 8 318 78
+c539 23 319 78
+c55c 15 320 78
+c571 c 321 78
+c57d 51 323 78
+c5ce 14 327 78
+c5e2 30 328 78
+c612 35 330 78
+c647 48 334 78
+c68f 17 338 78
+c6a6 43 339 78
+c6e9 14 342 78
+c6fd 1e 343 78
+c71b e 348 78
+c729 1e 349 78
+c747 e 350 78
+c755 1d 353 78
+c772 8 354 78
+c77a e 355 78
+c788 27 357 78
+c7af 6 358 78
+c7b5 4d 361 78
+c802 40 365 78
+c842 18 367 78
+c85a 4d 368 78
+c8a7 3e 379 78
+c8e5 30 381 78
+c915 12 384 78
+c927 13 385 78
+c93a 22 386 78
+FUNC c95c 2e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+c95c c 657 29
+c968 22 658 71
+c996 15 580 34
+c9ab 15 581 34
+c9c0 37 582 34
+c9f7 c 583 34
+ca03 1 583 34
+ca04 d 335 34
+ca11 4e 337 34
+ca5f 4d 338 34
+caac d 134 42
+cab9 65 135 42
+FUNC cb1e 44 0 dwarf2reader::CUFunctionInfoHandler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char)
+cb1e 39 135 42
+cb57 5 102 30
+cb5c 6 103 30
+FUNC cb62 41 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&)
+cb62 18 136 30
+cb7a 10 137 30
+cb8a 17 138 30
+cba1 2 139 30
+cba3 1 139 30
+FUNC cba4 2a5 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long)
+cba4 2d 144 30
+cbd1 a 145 30
+cbdb 58 146 30
+cc33 35 147 30
+cc68 32 146 30
+cc9a 2a 147 30
+ccc4 82 152 30
+cd46 18 153 30
+cd5e 1c 152 30
+cd7a 2f 153 30
+cda9 e 154 30
+cdb7 28 155 30
+cddf 12 157 30
+cdf1 2 158 30
+cdf3 12 160 30
+ce05 2 161 30
+ce07 c 163 30
+ce13 2 164 30
+ce15 2c 166 30
+ce41 8 172 30
+ce49 1 172 30
+FUNC ce4a 19c 0 dwarf2reader::CULineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int)
+ce4a 20 84 30
+ce6a 1c 85 30
+ce86 9c 87 30
+cf22 4f 89 30
+cf71 19 87 30
+cf8a 25 90 30
+cfaf 30 93 30
+cfdf 7 95 30
+FUNC cfe6 9f 0 dwarf2reader::CUFunctionInfoHandler::EndDIE(unsigned long long)
+cfe6 19 174 30
+cfff 1c 175 30
+d01b 65 177 30
+d080 5 178 30
+d085 1 178 30
+FUNC d086 164 0 dwarf2reader::CUFunctionInfoHandler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+d086 20 111 30
+d0a6 1c 112 30
+d0c2 c 126 30
+d0ce 23 115 30
+d0f1 26 116 30
+d117 1a 117 30
+d131 d 118 30
+d13e 1b 119 30
+d159 5f 120 30
+d1b8 c 124 30
+d1c4 1c 115 30
+d1e0 3 126 30
+d1e3 7 129 30
+FUNC d1ea 73 0 dwarf2reader::CULineInfoHandler::DefineDir(std::string const&, unsigned int)
+d1ea 13 52 30
+d1fd 45 54 30
+d242 15 55 30
+d257 6 56 30
+d25d 1 56 30
+FUNC d25e 23b 0 dwarf2reader::CULineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long)
+d25e 2c 60 30
+d28a 45 62 30
+d2cf 2f 65 30
+d2fe 24 66 30
+d322 b 68 30
+d32d e 69 30
+d33b 19 71 30
+d354 17 72 30
+d36b 93 74 30
+d3fe 64 77 30
+d462 30 79 30
+d492 7 81 30
+d499 1 81 30
+d49a 14 38 30
+d4ae 36 40 30
+d4e4 41 43 30
+d525 41 44 30
+d566 67 45 30
+d5cd 10 46 30
+d5dd 13 45 30
+d5f0 15 47 30
+d605 e 48 30
+d613 3d 49 30
+d650 20 50 30
+d670 14 38 30
+d684 36 40 30
+d6ba 41 43 30
+d6fb 41 44 30
+d73c 67 45 30
+d7a3 10 46 30
+d7b3 13 45 30
+d7c6 15 47 30
+d7db e 48 30
+d7e9 3d 49 30
+d826 20 50 30
+d846 12 125 74
+d858 12 125 74
+d86a 13 55 32
+d87d 35 55 32
+d8b2 13 98 32
+d8c5 35 98 32
+d8fa c 35 32
+d906 d 35 32
+d913 1 35 32
+d914 d 22 32
+d921 40 22 32
+d961 1 22 32
+d962 c 89 70
+d96e 1e 90 70
+d998 14 208 34
+d9ac c 190 67
+d9b8 a 190 67
+d9c2 c 259 67
+d9ce 21 259 67
+d9ef 1 259 67
+FUNC d9f0 13 0 std::auto_ptr<dwarf2reader::LineInfo>::operator->() const
+d9f0 c 283 35
+d9fc 7 286 67
+da03 1 286 67
+da11 5c 104 68
+da6d 1 104 68
+FUNC da6e 28 0 bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
+da6e c 2139 37
+da7a 1c 2140 37
+FUNC da96 5d 0 std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
+da96 d 2081 37
+daa3 12 2083 37
+dab5 1a 2084 37
+dacf 24 2085 37
+daf3 1 2085 37
+FUNC daf4 5d 0 std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+daf4 d 2044 37
+db01 12 2046 37
+db13 1a 2047 37
+db2d 24 2048 37
+db51 1 2048 37
+db52 c 84 70
+db5e 17 85 70
+db75 1 85 70
+FUNC db76 2d 0 std::pair<char const*, unsigned int> std::make_pair<char const*, unsigned int>(char const*, unsigned int)
+db76 c 144 37
+db82 21 145 70
+dba3 1 145 70
+dba4 c 84 70
+dbb0 23 85 70
+dbd3 1 85 70
+FUNC dbd4 3c 0 std::pair<unsigned long long, std::pair<char const*, unsigned int> > std::make_pair<unsigned long long, std::pair<char const*, unsigned int> >(unsigned long long, std::pair<char const*, unsigned int>)
+dbd4 1c 144 37
+dbf0 20 145 70
+dc10 d 89 70
+dc1d 64 90 70
+dc81 1 90 70
+dc82 c 89 70
+dc8e 2a 90 70
+dcb8 c 84 70
+dcc4 1d 85 70
+dce1 1 85 70
+FUNC dce2 3c 0 std::pair<unsigned long long, dwarf2reader::FunctionInfo*> std::make_pair<unsigned long long, dwarf2reader::FunctionInfo*>(unsigned long long, dwarf2reader::FunctionInfo*)
+dce2 1c 144 37
+dcfe 20 145 70
+dd2a a 190 34
+dd40 d 194 34
+dd4d 1 194 34
+dd4e c 603 72
+dd5a c 603 72
+FUNC dd66 2b 0 std::vector<std::string, std::allocator<std::string> >::begin() const
+dd66 c 342 39
+dd72 1f 343 71
+dd91 1 343 71
+FUNC dd92 2c 0 std::vector<std::string, std::allocator<std::string> >::end() const
+dd92 c 360 39
+dd9e 20 361 71
+ddca 5 666 72
+ddcf 1 666 72
+dddd 2b 759 72
+FUNC de08 3c 0 std::vector<std::string, std::allocator<std::string> >::size() const
+de08 c 402 39
+de14 30 403 71
+FUNC de44 2b 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::begin() const
+de44 c 342 39
+de50 1f 343 71
+de6f 1 343 71
+FUNC de70 2c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::end() const
+de70 c 360 39
+de7c 20 361 71
+dea9 31 759 72
+FUNC deda 3c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::size() const
+deda c 402 39
+dee6 30 403 71
+df16 c 603 72
+df22 c 603 72
+FUNC df2e 26 0 std::vector<std::string, std::allocator<std::string> >::end()
+df2e c 351 39
+df3a 1a 352 71
+df60 7 614 72
+df67 1 614 72
+FUNC df68 13 0 std::vector<std::string, std::allocator<std::string> >::max_size() const
+df68 c 407 39
+df74 7 408 71
+df7b 1 408 71
+df88 5 666 72
+df8d 1 666 72
+df9a d 623 72
+dfa7 5 624 72
+FUNC dfac 23 0 std::vector<std::string, std::allocator<std::string> >::begin()
+dfac c 333 39
+dfb8 17 334 71
+dfcf 1 334 71
+dfd0 c 35 32
+dfdc 26 35 32
+e00f 5c 104 68
+e06b 1 104 68
+e078 7 614 72
+e07f 1 614 72
+FUNC e080 35 0 dwarf2reader::SourceFileInfo::operator=(dwarf2reader::SourceFileInfo const&)
+e080 c 35 39
+e08c 29 35 32
+e0b5 1 35 32
+FUNC e0b6 13 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::max_size() const
+e0b6 c 407 39
+e0c2 7 408 71
+e0c9 1 408 71
+e0d6 d 623 72
+e0e3 5 624 72
+FUNC e0e8 3c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_range_check(unsigned long) const
+e0e8 13 515 39
+e0fb 15 517 71
+e110 14 518 71
+FUNC e124 3c 0 std::vector<std::string, std::allocator<std::string> >::_M_range_check(unsigned long) const
+e124 13 515 39
+e137 15 517 71
+e14c 14 518 71
+e16c 2a 654 72
+FUNC e196 42 0 std::vector<std::string, std::allocator<std::string> >::operator[](unsigned long)
+e196 c 494 39
+e1a2 36 495 71
+FUNC e1d8 32 0 std::vector<std::string, std::allocator<std::string> >::at(unsigned long)
+e1d8 c 534 39
+e1e4 12 536 71
+e1f6 14 537 71
+e216 32 654 72
+FUNC e248 42 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::operator[](unsigned long)
+e248 c 494 39
+e254 36 495 71
+FUNC e28a 32 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::at(unsigned long)
+e28a c 534 39
+e296 12 536 71
+e2a8 14 537 71
+FUNC e2bc 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_end()
+e2bc c 472 40
+e2c8 8 473 40
+FUNC e2d0 11 0 std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator()(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&) const
+e2d0 c 550 41
+e2dc 5 551 41
+e2e1 1 551 41
+FUNC e2e2 53 0 std::less<unsigned long long>::operator()(unsigned long long const&, unsigned long long const&) const
+e2e2 c 226 41
+e2ee 47 227 41
+e335 1 227 41
+FUNC e336 20 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator==(std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const&) const
+e336 c 209 41
+e342 14 210 40
+e356 c 84 70
+e362 18 85 70
+FUNC e37a 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_end()
+e37a c 472 41
+e386 8 473 40
+FUNC e38e 11 0 std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator()(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&) const
+e38e c 550 41
+e39a 5 551 41
+e39f 1 551 41
+FUNC e3a0 20 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator==(std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const&) const
+e3a0 c 209 41
+e3ac 14 210 40
+e3c0 c 84 70
+e3cc 18 85 70
+e3e4 c 180 34
+e3f0 13 181 34
+e403 1 181 34
+e410 22 409 34
+e43e d 207 42
+e44b 1 207 42
+FUNC e44c 35 0 bool __gnu_cxx::operator!=<std::string*, std::vector<std::string, std::allocator<std::string> > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > const&, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > const&)
+e44c d 699 42
+e459 28 700 72
+e481 1 700 72
+FUNC e482 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::allocator<std::string> >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::allocator<std::string>)
+e482 c 171 43
+e48e 2 173 73
+e490 1a 174 73
+e4aa 21 173 73
+e4cb 2 174 73
+e4cd 1 174 73
+FUNC e4ce 35 0 bool __gnu_cxx::operator!=<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&)
+e4ce d 699 43
+e4db 28 700 72
+e503 1 700 72
+FUNC e504 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, std::allocator<dwarf2reader::SourceFileInfo> >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, std::allocator<dwarf2reader::SourceFileInfo>)
+e504 c 171 43
+e510 2 173 73
+e512 1a 174 73
+e52c 21 173 73
+e54d 2 174 73
+e54f 1 174 73
+FUNC e550 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_value(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const*)
+e550 c 480 43
+e55c 8 481 40
+FUNC e564 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_key(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const*)
+e564 c 484 43
+e570 1c 485 40
+FUNC e58c 25 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator--()
+e58c c 194 43
+e598 14 196 40
+e5ac 5 197 40
+e5b1 1 197 40
+FUNC e5b2 25 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator--()
+e5b2 c 194 43
+e5be 14 196 40
+e5d2 5 197 40
+e5d7 1 197 40
+FUNC e5d8 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_value(std::_Rb_tree_node_base const*)
+e5d8 c 504 43
+e5e4 8 505 40
+FUNC e5ec 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_key(std::_Rb_tree_node_base const*)
+e5ec c 508 43
+e5f8 1c 509 40
+FUNC e614 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_value(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const*)
+e614 c 480 43
+e620 8 481 40
+FUNC e628 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_key(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const*)
+e628 c 484 43
+e634 1c 485 40
+FUNC e650 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_value(std::_Rb_tree_node_base const*)
+e650 c 504 43
+e65c 8 505 40
+FUNC e664 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_key(std::_Rb_tree_node_base const*)
+e664 c 508 43
+e670 1c 509 40
+e698 7 614 72
+e69f 1 614 72
+e6ac 7 98 68
+e6b3 1 98 68
+e6c0 1d 85 68
+e6dd 5 86 68
+e6e2 10 88 68
+FUNC e6f2 2a 0 std::_Vector_base<std::string, std::allocator<std::string> >::_M_allocate(unsigned long)
+e6f2 c 116 43
+e6fe 1e 117 71
+e728 7 98 68
+e72f 1 98 68
+e73c 1d 85 68
+e759 5 86 68
+e75e 16 88 68
+FUNC e774 2a 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_allocate(unsigned long)
+e774 c 116 43
+e780 1e 117 71
+e7aa 3a 104 68
+e7f0 2a 654 72
+FUNC e81a 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::operator[](unsigned long) const
+e81a c 509 43
+e826 36 510 71
+FUNC e85c 4e 0 std::string* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<std::string*, std::string*>(std::string*, std::string*, std::string*)
+e85c c 408 61
+e868 14 411 61
+e87c 1e 412 61
+e89a b 411 61
+e8a5 5 413 61
+FUNC e8aa 2b 0 std::string* std::__copy_backward_aux<std::string*, std::string*>(std::string*, std::string*, std::string*)
+e8aa c 432 44
+e8b6 4 440 61
+e8ba 1b 443 61
+e8d5 1 443 61
+e8e4 56 482 61
+e946 4 514 61
+e94a 4 515 61
+e94e 1b 517 61
+e969 1 517 61
+FUNC e96a 69 0 void std::_Construct<std::string, std::string>(std::string*, std::string const&)
+e96a d 77 44
+e977 5c 81 73
+e9d3 1 81 73
+FUNC e9d4 54 0 dwarf2reader::SourceFileInfo* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*)
+e9d4 c 408 61
+e9e0 1a 411 61
+e9fa 1e 412 61
+ea18 b 411 61
+ea23 5 413 61
+FUNC ea28 2b 0 dwarf2reader::SourceFileInfo* std::__copy_backward_aux<dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*)
+ea28 c 432 44
+ea34 4 440 61
+ea38 1b 443 61
+ea53 1 443 61
+ea62 56 482 61
+eac4 4 514 61
+eac8 4 515 61
+eacc 1b 517 61
+eae7 1 517 61
+FUNC eae8 69 0 void std::_Construct<dwarf2reader::SourceFileInfo, dwarf2reader::SourceFileInfo>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo const&)
+eae8 d 77 44
+eaf5 5c 81 73
+eb51 1 81 73
+eb52 c 69 70
+eb5e 20 69 70
+eb7e c 69 70
+eb8a 2a 69 70
+ebc1 5c 104 68
+ec1d 1 104 68
+ec2a 15 523 34
+ec3f 79 525 34
+ecb8 21 529 34
+ecd9 1 529 34
+ece6 14 229 42
+ed06 7 98 68
+ed0d 1 98 68
+ed1a 1d 85 68
+ed37 5 86 68
+ed3c 10 88 68
+FUNC ed4c 29 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_get_node()
+ed4c c 355 44
+ed58 1d 356 40
+ed75 1 356 40
+FUNC ed76 b6 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_create_node(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+ed76 d 363 44
+ed83 e 365 40
+ed91 3c 367 40
+edcd b 373 40
+edd8 11 367 40
+ede9 b 368 40
+edf4 12 370 40
+ee06 b 371 40
+ee11 13 368 40
+ee24 8 373 40
+FUNC ee2c cd 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+ee2c d 787 44
+ee39 15 789 40
+ee4e 5d 792 40
+eeab 24 796 40
+eecf f 798 40
+eede 1b 799 40
+eef9 1 799 40
+FUNC eefa 1ef 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::insert_unique(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+eefa d 869 44
+ef07 e 871 40
+ef15 e 872 40
+ef23 4 873 40
+ef27 2 874 40
+ef29 6 876 40
+ef2f 35 877 40
+ef64 2a 878 40
+ef8e 6 874 40
+ef94 12 880 40
+efa6 a 881 40
+efb0 24 882 40
+efd4 51 883 40
+f025 b 885 40
+f030 36 886 40
+f066 4e 887 40
+f0b4 35 888 40
+f0e9 1 888 40
+FUNC f0ea 20 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::insert(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+f0ea c 359 45
+f0f6 14 360 45
+f116 7 98 68
+f11d 1 98 68
+f12a 1d 85 68
+f147 5 86 68
+f14c 1d 88 68
+f169 1 88 68
+FUNC f16a 29 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_get_node()
+f16a c 355 45
+f176 1d 356 40
+f193 1 356 40
+FUNC f194 5f 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_create_node(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f194 d 363 45
+f1a1 e 365 40
+f1af 3c 367 40
+f1eb 8 373 40
+f1f3 1 373 40
+FUNC f1f4 cd 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f1f4 d 787 45
+f201 15 789 40
+f216 5d 792 40
+f273 24 796 40
+f297 f 798 40
+f2a6 1b 799 40
+f2c1 1 799 40
+FUNC f2c2 1ef 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::insert_unique(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f2c2 d 869 45
+f2cf e 871 40
+f2dd e 872 40
+f2eb 4 873 40
+f2ef 2 874 40
+f2f1 6 876 40
+f2f7 35 877 40
+f32c 2a 878 40
+f356 6 874 40
+f35c 12 880 40
+f36e a 881 40
+f378 24 882 40
+f39c 51 883 40
+f3ed b 885 40
+f3f8 36 886 40
+f42e 4e 887 40
+f47c 35 888 40
+f4b1 1 888 40
+FUNC f4b2 20 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::insert(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f4b2 c 359 45
+f4be 14 360 45
+FUNC f4d2 19 0 void std::_Destroy<std::string>(std::string*)
+f4d2 c 106 45
+f4de d 107 73
+f4eb 1 107 73
+FUNC f4ec 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __false_type)
+f4ec c 119 45
+f4f8 2 121 73
+f4fa 13 122 73
+f50d 21 121 73
+f52e 2 122 73
+FUNC f530 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >)
+f530 c 148 45
+f53c 1c 155 73
+f565 6 82 79
+f56b 2 85 79
+f56d 24 86 79
+f591 2c 85 79
+f5bd b 87 79
+f5c8 b 89 79
+f5d3 12 91 79
+f5e5 b 92 79
+f5f0 13 89 79
+f603 9 92 79
+f618 23 113 79
+f63b 1 113 79
+f648 1b 254 79
+f663 1 254 79
+FUNC f664 430 0 std::vector<std::string, std::allocator<std::string> >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::string const&)
+f664 14 249 47
+f678 14 251 78
+f68c 22 253 78
+f6ae f 255 78
+f6bd 12 256 78
+f6cf 55 257 78
+f724 4b 260 78
+f76f e 264 78
+f77d 15 265 78
+f792 e 266 78
+f7a0 1d 271 78
+f7bd 8 272 78
+f7c5 e 273 78
+f7d3 27 275 78
+f7fa 6 276 78
+f800 55 279 78
+f855 25 284 78
+f87a b 285 78
+f885 4f 286 78
+f8d4 3 284 78
+f8d7 13 279 78
+f8ea e 286 78
+f8f8 4d 298 78
+f945 30 299 78
+f975 12 302 78
+f987 13 303 78
+f99a 23 304 78
+f9bd 3 298 78
+f9c0 13 286 78
+f9d3 b 292 78
+f9de 39 294 78
+fa17 23 295 78
+fa3a 8 296 78
+fa42 16 294 78
+fa58 3 296 78
+fa5b 19 292 78
+fa74 19 298 78
+fa8d 7 304 78
+FUNC fa94 70 0 std::vector<std::string, std::allocator<std::string> >::push_back(std::string const&)
+fa94 c 602 47
+faa0 10 604 71
+fab0 1e 606 71
+face 11 607 71
+fadf 25 610 71
+FUNC fb04 19 0 void std::_Destroy<dwarf2reader::SourceFileInfo>(dwarf2reader::SourceFileInfo*)
+fb04 c 106 47
+fb10 d 107 73
+fb1d 1 107 73
+FUNC fb1e 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __false_type)
+fb1e c 119 47
+fb2a 2 121 73
+fb2c 13 122 73
+fb3f 21 121 73
+fb60 2 122 73
+FUNC fb62 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >)
+fb62 c 148 47
+fb6e 1c 155 73
+fb97 6 82 79
+fb9d 2 85 79
+fb9f 24 86 79
+fbc3 2c 85 79
+fbef b 87 79
+fbfa b 89 79
+fc05 12 91 79
+fc17 b 92 79
+fc22 13 89 79
+fc35 9 92 79
+fc4a 23 113 79
+fc6d 1 113 79
+fc7a 1b 254 79
+fc95 1 254 79
+FUNC fc96 43d 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_insert_aux(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, dwarf2reader::SourceFileInfo const&)
+fc96 14 249 47
+fcaa 14 251 78
+fcbe 22 253 78
+fce0 f 255 78
+fcef 12 256 78
+fd01 55 257 78
+fd56 4b 260 78
+fda1 e 264 78
+fdaf 15 265 78
+fdc4 e 266 78
+fdd2 1d 271 78
+fdef 8 272 78
+fdf7 e 273 78
+fe05 27 275 78
+fe2c 6 276 78
+fe32 55 279 78
+fe87 25 284 78
+feac b 285 78
+feb7 4f 286 78
+ff06 3 284 78
+ff09 13 279 78
+ff1c e 286 78
+ff2a 4d 298 78
+ff77 36 299 78
+ffad 12 302 78
+ffbf 13 303 78
+ffd2 2a 304 78
+fffc 3 298 78
+ffff 13 286 78
+10012 b 292 78
+1001d 39 294 78
+10056 23 295 78
+10079 8 296 78
+10081 16 294 78
+10097 3 296 78
+1009a 19 292 78
+100b3 19 298 78
+100cc 7 304 78
+100d3 1 304 78
+FUNC 100d4 70 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::push_back(dwarf2reader::SourceFileInfo const&)
+100d4 c 602 47
+100e0 10 604 71
+100f0 1e 606 71
+1010e 11 607 71
+1011f 25 610 71
+FUNC 10144 16c 0 Start
+10144 17 610 71
+1015b 40 49 48
+1019b 6 51 48
+101a1 3f 53 48
+101e0 7 54 48
+101e7 5 55 48
+101ec 2a 58 48
+10216 61 61 48
+10277 7 62 48
+1027e 2 63 48
+10280 29 66 48
+102a9 7 67 48
+FUNC 102b0 108 0 Usage
+102b0 19 70 48
+102c9 30 71 48
+102f9 29 73 48
+10322 30 74 48
+10352 30 75 48
+10382 30 76 48
+103b2 6 77 48
+FUNC 103b8 3af 0 SetupOptions
+103b8 21 80 48
+103d9 8 82 48
+103e1 6 85 48
+103e7 10 86 48
+103f7 2e 88 48
+10425 2f 94 48
+10454 2a 91 48
+1047e 23 95 48
+104a1 3e 97 48
+104df 11 98 48
+104f0 7c 99 48
+1056c c 100 48
+10578 5 99 48
+1057d 3e 101 48
+105bb 11 102 48
+105cc 3e 103 48
+1060a 11 104 48
+1061b 37 106 48
+10652 b 107 48
+1065d c 108 48
+10669 b 113 48
+10674 c 114 48
+10680 14 119 48
+10694 30 120 48
+106c4 b 121 48
+106cf c 122 48
+106db 81 127 48
+1075c b 128 48
+10767 1 128 48
+FUNC 10768 a7 0 main
+10768 13 131 48
+1077b 37 132 48
+107b2 1e 135 48
+107d0 e 136 48
+107de 8 137 48
+107e6 17 139 48
+107fd c 141 48
+10809 6 142 48
+1080f 1 142 48
+10810 c 47 49
+1081c 1a 48 49
+10836 2 49 49
+10838 c 47 49
+10844 1a 48 49
+1085e 2 49 49
+FUNC 10860 cb 0 google_breakpad::FileID::FileIdentifier(unsigned char*)
+10860 f 51 49
+1086f 16 52 49
+10885 6 53 49
+1088b f 54 49
+1089a b 57 49
+108a5 7 62 49
+108ac 2 63 49
+108ae 1c 64 49
+108ca 32 63 49
+108fc b 67 49
+10907 12 68 49
+10919 10 70 49
+10929 2 71 49
+1092b 1 71 49
+FUNC 1092c f2 0 google_breakpad::FileID::MachoIdentifier(int, unsigned char*)
+1092c 10 73 49
+1093c 15 74 49
+10951 20 76 49
+10971 f 77 49
+10980 20 79 49
+109a0 c 80 49
+109ac 69 82 49
+10a15 9 83 49
+FUNC 10a1e fb 0 google_breakpad::FileID::ConvertIdentifierToString(unsigned char const*, char*, int)
+10a1e c 87 49
+10a2a 7 88 49
+10a31 c 89 49
+10a3d 15 90 49
+10a52 12 91 49
+10a64 18 93 49
+10a7c e 94 49
+10a8a 2b 96 49
+10ab5 2b 97 49
+10ae0 17 89 49
+10af7 20 101 49
+10b17 2 102 49
+10b19 1 102 49
+FUNC 10b1a 13 0 NXHostByteOrder
+10b1a c 144 56
+10b26 5 147 56
+10b2b 2 153 56
+10b2d 1 153 56
+10b2e c 56 51
+10b3a 1a 57 51
+10b54 1e 58 51
+10b72 2 59 51
+10b74 c 56 51
+10b80 1a 57 51
+10b9a 1e 58 51
+10bb8 2 59 51
+10bba c 61 51
+10bc6 e 62 51
+10bd4 11 63 51
+10be5 2 64 51
+10be7 1 64 51
+10be8 c 61 51
+10bf4 e 62 51
+10c02 11 63 51
+10c13 2 64 51
+10c15 1 64 51
+FUNC 10c16 477 0 MacFileUtilities::MachoID::UpdateCRC(unsigned char*, unsigned long)
+10c16 c 74 51
+10c22 11 82 51
+10c33 14 83 51
+10c47 5 86 51
+10c4c 9 87 51
+10c55 7 88 51
+10c5c 18b 90 51
+10de7 6 91 51
+10ded 14 89 51
+10e01 23 93 51
+10e24 23 94 51
+10e47 d 86 51
+10e54 f 98 51
+10e63 6 100 51
+10e69 18b 101 51
+10ff4 6 102 51
+10ffa c 99 51
+11006 13 105 51
+11019 8 106 51
+11021 10 104 51
+11031 23 108 51
+11054 23 109 51
+11077 14 110 51
+1108b 2 112 51
+1108d 1 112 51
+FUNC 1108e 2c 0 MacFileUtilities::MachoID::UpdateMD5(unsigned char*, unsigned long)
+1108e c 114 51
+1109a 1e 115 51
+110b8 2 116 51
+FUNC 110ba 2c 0 MacFileUtilities::MachoID::UpdateSHA1(unsigned char*, unsigned long)
+110ba c 118 51
+110c6 1e 119 51
+110e4 2 120 51
+FUNC 110e6 121 0 MacFileUtilities::MachoID::Update(MacFileUtilities::MachoWalker*, unsigned long, unsigned long)
+110e6 f 122 51
+110f5 1b 123 51
+11110 e 129 51
+1111e 5 130 51
+11123 9 131 51
+1112c 7 132 51
+11133 a 133 51
+1113d 6 135 51
+11143 7 136 51
+1114a 35 139 51
+1117f 6c 142 51
+111eb 10 143 51
+111fb a 130 51
+11205 2 145 51
+11207 1 145 51
+FUNC 11208 cf 0 MacFileUtilities::MachoID::UUIDCommand(int, unsigned char*)
+11208 14 147 51
+1121c 25 149 51
+11241 7 151 51
+11248 19 152 51
+11261 9 153 51
+1126a 8 157 51
+11272 1f 158 51
+11291 9 159 51
+1129a 36 162 51
+112d0 7 163 51
+112d7 1 163 51
+FUNC 112d8 224 0 MacFileUtilities::MachoID::IDCommand(int, unsigned char*)
+112d8 15 165 51
+112ed 25 167 51
+11312 7 169 51
+11319 19 170 51
+11332 c 171 51
+1133e c 175 51
+1134a 6 180 51
+11350 7 181 51
+11357 9 182 51
+11360 9 183 51
+11369 28 185 51
+11391 33 186 51
+113c4 1e 185 51
+113e2 10 189 51
+113f2 10 190 51
+11402 10 191 51
+11412 d 192 51
+1141f 10 193 51
+1142f 10 194 51
+1143f 10 195 51
+1144f d 196 51
+1145c 17 197 51
+11473 17 198 51
+1148a 17 199 51
+114a1 14 200 51
+114b5 9 202 51
+114be 36 205 51
+114f4 8 206 51
+FUNC 114fc d1 0 MacFileUtilities::MachoID::Adler32(int)
+114fc 14 208 51
+11510 25 209 51
+11535 27 210 51
+1155c d 211 51
+11569 19 213 51
+11582 9 214 51
+1158b 3b 216 51
+115c6 7 217 51
+115cd 1 217 51
+FUNC 115ce f8 0 MacFileUtilities::MachoID::MD5(int, unsigned char*)
+115ce 14 219 51
+115e2 25 220 51
+11607 27 221 51
+1162e 19 223 51
+11647 19 224 51
+11660 9 225 51
+11669 17 227 51
+11680 9 228 51
+11689 36 231 51
+116bf 7 232 51
+FUNC 116c6 f8 0 MacFileUtilities::MachoID::SHA1(int, unsigned char*)
+116c6 14 234 51
+116da 25 235 51
+116ff 27 236 51
+11726 19 238 51
+1173f 19 239 51
+11758 9 240 51
+11761 17 242 51
+11778 9 243 51
+11781 36 246 51
+117b7 7 247 51
+FUNC 117be 378 0 MacFileUtilities::MachoID::WalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+117be 2b 251 51
+117e9 6 252 51
+117ef e 254 51
+117fd 38 257 51
+11835 f 258 51
+11844 9 260 51
+1184d 17 261 51
+11864 20 266 51
+11884 f 267 51
+11893 d 271 51
+118a0 c 273 51
+118ac 38 274 51
+118e4 f 275 51
+118f3 9 277 51
+118fc 1f 278 51
+1191b 14 282 51
+1192f 2b 283 51
+1195a d 285 51
+11967 19 273 51
+11980 e 287 51
+1198e 38 290 51
+119c6 f 291 51
+119d5 9 293 51
+119de 17 294 51
+119f5 20 299 51
+11a15 f 300 51
+11a24 d 304 51
+11a31 c 306 51
+11a3d 38 307 51
+11a75 f 308 51
+11a84 9 310 51
+11a8d 1f 311 51
+11aac 1a 315 51
+11ac6 39 316 51
+11aff d 318 51
+11b0c 11 306 51
+11b1d 10 323 51
+11b2d 9 324 51
+FUNC 11b36 95 0 MacFileUtilities::MachoID::UUIDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+11b36 1e 328 51
+11b54 a 329 51
+11b5e 6 331 51
+11b64 2f 333 51
+11b93 9 335 51
+11b9c 6 337 51
+11ba2 14 338 51
+11bb6 9 340 51
+11bbf a 344 51
+11bc9 2 345 51
+11bcb 1 345 51
+FUNC 11bcc 95 0 MacFileUtilities::MachoID::IDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+11bcc 1e 349 51
+11bea a 350 51
+11bf4 6 351 51
+11bfa 2f 353 51
+11c29 9 354 51
+11c32 6 356 51
+11c38 14 357 51
+11c4c 9 359 51
+11c55 a 363 51
+11c5f 2 364 51
+11c61 1 364 51
+FUNC 11c62 1c 0 _OSSwapInt32
+11c62 f 53 55
+11c71 8 55 55
+11c79 3 56 55
+11c7c 2 57 55
+FUNC 11c7e 19 0 NXSwapInt
+11c7e f 52 56
+11c8d 8 54 56
+11c95 2 55 56
+11c97 1 55 56
+FUNC 11c98 13 0 NXHostByteOrder
+11c98 c 144 56
+11ca4 5 147 56
+11ca9 2 153 56
+11cab 1 153 56
+11cac c 52 54
+11cb8 12 54 54
+11cca 1a 55 54
+11ce4 2 56 54
+11ce6 c 52 54
+11cf2 12 54 54
+11d04 1a 55 54
+11d1e 2 56 54
+11d20 c 58 54
+11d2c a 59 54
+11d36 d 60 54
+11d43 2 61 54
+11d45 1 61 54
+11d46 c 58 54
+11d52 a 59 54
+11d5c d 60 54
+11d69 2 61 54
+11d6b 1 61 54
+FUNC 11d6c 37 0 MacFileUtilities::MachoWalker::ValidateCPUType(int)
+11d6c c 63 54
+11d78 6 66 54
+11d7e 8 67 54
+11d86 6 68 54
+11d8c b 69 54
+11d97 7 74 54
+11d9e 3 80 54
+11da1 2 81 54
+11da3 1 81 54
+FUNC 11da4 50 0 MacFileUtilities::MachoWalker::ReadBytes(void*, unsigned long, long long)
+11da4 18 96 54
+11dbc 36 97 54
+11df2 2 98 54
+FUNC 11df4 73 0 MacFileUtilities::MachoWalker::CurrentHeader(mach_header_64*, long long*)
+11df4 c 100 54
+11e00 a 101 54
+11e0a 37 102 54
+11e41 11 103 54
+11e52 9 104 54
+11e5b a 107 54
+11e65 2 108 54
+11e67 1 108 54
+FUNC 11e68 2a6 0 MacFileUtilities::MachoWalker::FindHeader(int, long long&)
+11e68 c 110 54
+11e74 15 111 54
+11e89 31 114 54
+11eba c 115 54
+11ec6 10 117 54
+11ed6 4 120 54
+11eda 14 121 54
+11eee 4 122 54
+11ef2 11 129 54
+11f03 28 124 54
+11f2b c 126 54
+11f37 31 133 54
+11f68 c 134 54
+11f74 14 136 54
+11f88 b 137 54
+11f93 8 139 54
+11f9b c 140 54
+11fa7 10 142 54
+11fb7 c 143 54
+11fc3 10 146 54
+11fd3 31 148 54
+12004 c 149 54
+12010 f 151 54
+1201f 14 152 54
+12033 16 154 54
+12049 c 158 54
+12055 31 159 54
+12086 9 160 54
+1208f f 162 54
+1209e 1c 163 54
+120ba 8 165 54
+120c2 10 166 54
+120d2 9 167 54
+120db 16 170 54
+120f1 11 158 54
+12102 a 174 54
+1210c 2 175 54
+FUNC 1210e 109 0 MacFileUtilities::MachoWalker::WalkHeaderCore(long long, unsigned int, bool)
+1210e 1e 224 54
+1212c c 225 54
+12138 2f 227 54
+12167 c 228 54
+12173 6 230 54
+12179 14 231 54
+1218d 5b 234 54
+121e8 12 237 54
+121fa 11 225 54
+1220b a 240 54
+12215 2 241 54
+12217 1 241 54
+FUNC 12218 10e 0 MacFileUtilities::MachoWalker::WalkHeader64AtOffset(long long)
+12218 18 203 54
+12230 2f 205 54
+1225f c 206 54
+1226b e 208 54
+12279 6 209 54
+1227f 14 210 54
+12293 9 212 54
+1229c a 213 54
+122a6 f 214 54
+122b5 15 215 54
+122ca 2b 216 54
+122f5 a 217 54
+122ff a 218 54
+12309 11 219 54
+1231a a 220 54
+12324 2 221 54
+FUNC 12326 143 0 MacFileUtilities::MachoWalker::WalkHeaderAtOffset(long long)
+12326 18 177 54
+1233e 2f 179 54
+1236d c 180 54
+12379 e 182 54
+12387 6 183 54
+1238d 14 184 54
+123a1 2e 189 54
+123cf 7 190 54
+123d6 9 192 54
+123df a 193 54
+123e9 f 194 54
+123f8 15 195 54
+1240d 2b 196 54
+12438 a 197 54
+12442 a 198 54
+1244c 11 199 54
+1245d a 200 54
+12467 2 201 54
+12469 1 201 54
+FUNC 1246a 99 0 MacFileUtilities::MachoWalker::WalkHeader(int)
+1246a c 83 54
+12476 15 84 54
+1248b 1d 86 54
+124a8 d 87 54
+124b5 21 88 54
+124d6 21 90 54
+124f7 a 93 54
+12501 2 94 54
+12503 1 94 54
+FUNC 12504 1c 0 _OSSwapInt32
+12504 f 53 55
+12513 8 55 55
+1251b 3 56 55
+1251e 2 57 55
+FUNC 12520 2b 0 _OSSwapInt64
+12520 12 64 55
+12532 11 69 55
+12543 6 70 55
+12549 2 71 55
+1254b 1 71 55
+FUNC 1254c 19 0 NXSwapLong
+1254c f 61 56
+1255b 8 63 56
+12563 2 64 56
+12565 1 64 56
+FUNC 12566 1f 0 NXSwapLongLong
+12566 12 70 56
+12578 b 72 56
+12583 2 73 56
+12585 1 73 56
+FUNC 12586 32 0 breakpad_swap_uuid_command(breakpad_uuid_command*, NXByteOrder)
+12586 c 37 57
+12592 11 39 57
+125a3 13 40 57
+125b6 2 41 57
+FUNC 125b8 da 0 breakpad_swap_segment_command_64(segment_command_64*, NXByteOrder)
+125b8 c 44 57
+125c4 11 46 57
+125d5 13 47 57
+125e8 17 49 57
+125ff 17 50 57
+12616 17 51 57
+1262d 17 52 57
+12644 13 54 57
+12657 13 55 57
+1266a 13 56 57
+1267d 13 57 57
+12690 2 58 57
+FUNC 12692 a4 0 breakpad_swap_mach_header_64(mach_header_64*, NXByteOrder)
+12692 c 61 57
+1269e 11 63 57
+126af 13 64 57
+126c2 13 65 57
+126d5 13 66 57
+126e8 13 67 57
+126fb 13 68 57
+1270e 13 69 57
+12721 13 70 57
+12734 2 71 57
+FUNC 12736 1d1 0 breakpad_swap_section_64(section_64*, unsigned int, NXByteOrder)
+12736 d 75 57
+12743 c 77 57
+1274f 33 78 57
+12782 33 79 57
+127b5 2d 81 57
+127e2 2d 82 57
+1280f 2d 83 57
+1283c 2d 84 57
+12869 2d 85 57
+12896 2d 86 57
+128c3 2d 87 57
+128f0 11 77 57
+12901 6 89 57
+12907 1 89 57
+12908 12 9 58
+1291a 4f 11 58
+12969 2 12 58
+1296b 1 12 58
+1296c 12 9 58
+1297e 4f 11 58
+129cd 2 12 58
+129cf 1 12 58
+129d0 13 14 58
+129e3 2a 14 58
+12a0d 1 14 58
+12a0e 13 14 58
+12a21 2a 14 58
+12a4b 1 14 58
+12a4c 13 14 58
+12a5f 2a 14 58
+12a89 1 14 58
+FUNC 12a8a bb 0 dwarf2reader::ByteReader::SetOffsetSize(unsigned char)
+12a8a 19 16 58
+12aa3 a 17 58
+12aad 48 18 58
+12af5 6 19 58
+12afb 23 20 58
+12b1e 21 22 58
+12b3f 6 24 58
+12b45 1 24 58
+FUNC 12b46 bb 0 dwarf2reader::ByteReader::SetAddressSize(unsigned char)
+12b46 19 26 58
+12b5f a 27 58
+12b69 48 28 58
+12bb1 6 29 58
+12bb7 23 30 58
+12bda 21 32 58
+12bfb 6 34 58
+12c01 1 34 58
+FUNC 12c02 a2 0 dwarf2reader::ByteReader::ReadFourBytes(char const*) const
+12c02 c 24 59
+12c0e c 25 64
+12c1a d 26 64
+12c27 f 27 64
+12c36 f 28 64
+12c45 b 29 64
+12c50 27 30 64
+12c77 2b 32 64
+12ca2 2 34 64
+FUNC 12ca4 40e 0 dwarf2reader::ByteReader::ReadEightBytes(char const*) const
+12ca4 11 36 59
+12cb5 1a 37 64
+12ccf 1b 38 64
+12cea 1d 39 64
+12d07 1d 40 64
+12d24 1d 41 64
+12d41 1d 42 64
+12d5e 1d 43 64
+12d7b 1d 44 64
+12d98 f 45 64
+12da7 18f 47 64
+12f36 172 50 64
+130a8 a 52 64
+130b2 2 52 64
+FUNC 130b4 a6 0 ReadInitialLength
+130b4 15 29 60
+130c9 18 30 60
+130e1 6 31 60
+130e7 d 35 60
+130f4 13 36 60
+13107 9 37 60
+13110 1a 38 60
+1312a 13 40 60
+1313d 9 41 60
+13146 12 43 60
+13158 2 44 60
+1315a 1f 47 60
+13179 65 50 60
+131de 1f 47 60
+131fd 65 50 60
+FUNC 13262 393 0 dwarf2reader::CompilationUnit::SkipAttribute(char const*, dwarf2reader::DwarfForm)
+13262 14 133 60
+13276 82 136 60
+132f8 1f 139 60
+13317 a 140 60
+13321 21 141 60
+13342 c 147 60
+1334e e 151 60
+1335c e 155 60
+1336a e 159 60
+13378 27 162 60
+1339f 1c 166 60
+133bb 10 167 60
+133cb 1c 171 60
+133e7 10 172 60
+133f7 1e 175 60
+13415 56 180 60
+1346b d 181 60
+13478 1e 182 60
+13496 11 183 60
+134a7 1e 184 60
+134c5 24 189 60
+134e9 26 192 60
+1350f 23 195 60
+13532 22 198 60
+13554 15 199 60
+13569 1b 203 60
+13584 30 206 60
+135b4 30 208 60
+135e4 a 209 60
+135ee 7 210 60
+135f5 1 210 60
+FUNC 135f6 29b 0 dwarf2reader::CompilationUnit::ReadHeader()
+135f6 14 217 60
+1360a 9 218 60
+13613 4e 221 60
+13661 17 223 60
+13678 a 224 60
+13682 f 225 60
+13691 4e 227 60
+136df 1e 228 60
+136fd 6 229 60
+13703 5e 231 60
+13761 1e 232 60
+1377f 18 233 60
+13797 4c 235 60
+137e3 1d 236 60
+13800 1c 237 60
+1381c 5 238 60
+13821 9 240 60
+1382a 60 245 60
+1388a 7 247 60
+13891 1 247 60
+FUNC 13892 a57 0 dwarf2reader::CompilationUnit::ProcessAttribute(unsigned long long, char const*, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm)
+13892 24 299 60
+138b6 8a 302 60
+13940 1f 307 60
+1395f a 308 60
+13969 36 309 60
+1399f 5b 316 60
+139fa c 317 60
+13a06 5b 322 60
+13a61 e 323 60
+13a6f 55 328 60
+13ac4 e 329 60
+13ad2 55 334 60
+13b27 e 335 60
+13b35 6 338 60
+13b3b 9a 340 60
+13bd5 33 341 60
+13c08 25 340 60
+13c2d 5c 348 60
+13c89 10 349 60
+13c99 5c 354 60
+13cf5 10 355 60
+13d05 55 359 60
+13d5a 1e 360 60
+13d78 56 365 60
+13dce d 366 60
+13ddb 55 368 60
+13e30 1e 369 60
+13e4e 11 370 60
+13e5f 55 372 60
+13eb4 1e 373 60
+13ed2 29 378 60
+13efb 4a 380 60
+13f45 f 381 60
+13f54 29 385 60
+13f7d 4c 387 60
+13fc9 11 388 60
+13fda 1b 392 60
+13ff5 4c 394 60
+14041 11 395 60
+14052 22 399 60
+14074 4e 401 60
+140c2 15 402 60
+140d7 3c 406 60
+14113 1b 408 60
+1412e 54 409 60
+14182 f 411 60
+14191 9a 413 60
+1422b 24 414 60
+1424f 25 413 60
+14274 30 418 60
+142a4 30 420 60
+142d4 a 421 60
+142de b 422 60
+142e9 1 422 60
+142ea 1f 489 60
+14309 3a 491 60
+14343 a 492 60
+1434d 6 493 60
+14353 1 493 60
+14354 1f 489 60
+14373 3a 491 60
+143ad a 492 60
+143b7 6 493 60
+143bd 1 493 60
+FUNC 143be b5 0 dwarf2reader::CompilationUnit::ProcessDIE(unsigned long long, char const*, dwarf2reader::CompilationUnit::Abbrev const&)
+143be 19 426 60
+143d7 13 427 60
+143ea 46 430 60
+14430 3a 427 60
+1446a 3 432 60
+1446d 6 433 60
+14473 1 433 60
+FUNC 14474 85 0 dwarf2reader::CompilationUnit::SkipDIE(char const*, dwarf2reader::CompilationUnit::Abbrev const&)
+14474 c 122 60
+14480 13 123 60
+14493 27 126 60
+144ba 3a 123 60
+144f4 3 128 60
+144f7 2 129 60
+144f9 1 129 60
+FUNC 144fa be4 0 dwarf2reader::LineInfo::ProcessOneOpcode(dwarf2reader::ByteReader*, dwarf2reader::LineInfoHandler*, dwarf2reader::LineInfoHeader const&, char const*, dwarf2reader::LineStateMachine*, unsigned long*, unsigned long, bool*)
+144fa 18 593 60
+14512 a 594 60
+1451c 18 596 60
+14534 8 597 60
+1453c 5 598 60
+14541 19 602 60
+1455a f 603 60
+14569 50 605 60
+145b9 46 607 60
+145ff e0 610 60
+146df 6 612 60
+146e5 22 615 60
+14707 22 616 60
+14729 7 617 60
+14730 b 618 60
+1473b f 619 60
+1474a 5a 623 60
+147a4 7 625 60
+147ab b 626 60
+147b6 f 627 60
+147c5 28 631 60
+147ed e 632 60
+147fb 144 635 60
+1493f 6 637 60
+14945 9e 640 60
+149e3 5 642 60
+149e8 22 644 60
+14a0a e 645 60
+14a18 1c 646 60
+14a34 2b 652 60
+14a5f b 653 60
+14a6a 22 658 60
+14a8c e 659 60
+14a9a 8 660 60
+14aa2 5 662 60
+14aa7 22 664 60
+14ac9 e 665 60
+14ad7 9 666 60
+14ae0 5 668 60
+14ae5 12 670 60
+14af7 5 672 60
+14afc 7 674 60
+14b03 5 676 60
+14b08 16 678 60
+14b1e 9 679 60
+14b27 d9 682 60
+14c00 6 684 60
+14c06 1f 687 60
+14c25 5 689 60
+14c2a 40 693 60
+14c6a d6 696 60
+14d40 6 698 60
+14d46 1c 701 60
+14d62 5 703 60
+14d67 1f 706 60
+14d86 d 707 60
+14d93 13 708 60
+14da6 26 710 60
+14dcc 5 711 60
+14dd1 50 713 60
+14e21 7 715 60
+14e28 b 716 60
+14e33 f 717 60
+14e42 18 725 60
+14e5a f 726 60
+14e69 5 728 60
+14e6e 6 730 60
+14e74 28 732 60
+14e9c d 733 60
+14ea9 22 735 60
+14ecb e 736 60
+14ed9 22 739 60
+14efb e 740 60
+14f09 22 743 60
+14f2b e 744 60
+14f39 a 746 60
+14f43 fd 748 60
+15040 a 758 60
+1504a 9 759 60
+15053 1c 761 60
+1506f d 762 60
+1507c e 763 60
+1508a 2e 759 60
+150b8 b 769 60
+150c3 10 770 60
+150d3 b 771 60
+FUNC 150de 14b 0 dwarf2reader::LineInfo::ReadLines()
+150de e 773 60
+150ec 9 778 60
+150f5 17 782 60
+1510c 8 783 60
+15114 6 785 60
+1511a 9 787 60
+15123 5 788 60
+15128 19 789 60
+15141 5 790 60
+15146 4a 793 60
+15190 6 794 60
+15196 4a 796 60
+151e0 a 797 60
+151ea f 790 60
+151f9 15 788 60
+1520e 14 801 60
+15222 7 802 60
+15229 1 802 60
+FUNC 1522a 4fd 0 dwarf2reader::CompilationUnit::ReadAbbrevs()
+1522a 18 60 60
+15242 e 61 60
+15250 58 65 60
+152a8 38 66 60
+152e0 44 65 60
+15324 2a 66 60
+1534e 45 68 60
+15393 16 69 60
+153a9 1d 75 60
+153c6 6 76 60
+153cc 40 77 60
+1540c b 80 60
+15417 1f 82 60
+15436 e 84 60
+15444 6 77 60
+1544a 1f 68 60
+15469 a 84 60
+15473 1d 79 60
+15490 6 86 60
+15496 a 87 60
+154a0 3d 89 60
+154dd 1f 90 60
+154fc a 91 60
+15506 6 92 60
+1550c 3d 94 60
+15549 1d 95 60
+15566 5 96 60
+1556b 3d 98 60
+155a8 1f 101 60
+155c7 a 102 60
+155d1 3d 104 60
+1560e 1f 105 60
+1562d a 106 60
+15637 c 107 60
+15643 6 111 60
+15649 6 112 60
+1564f 32 113 60
+15681 47 115 60
+156c8 30 116 60
+156f8 24 79 60
+1571c b 118 60
+15727 1 118 60
+FUNC 15728 5dc 0 dwarf2reader::LineInfo::ReadHeader()
+15728 18 503 60
+15740 9 504 60
+15749 17 508 60
+15760 a 510 60
+1576a f 511 60
+15779 60 512 60
+157d9 44 516 60
+1581d 1e 518 60
+1583b 6 519 60
+15841 1e 521 60
+1585f 18 522 60
+15877 1d 524 60
+15894 5 525 60
+15899 20 527 60
+158b9 5 528 60
+158be c 530 60
+158ca 5 531 60
+158cf 1d 533 60
+158ec 5 534 60
+158f1 1d 536 60
+1590e 5 537 60
+15913 45 539 60
+15958 1f 540 60
+15977 19 541 60
+15990 15 542 60
+159a5 1f 539 60
+159c4 30 543 60
+159f4 5 544 60
+159f9 14 542 60
+15a0d e 548 60
+15a1b 7 549 60
+15a22 5 550 60
+15a27 6 551 60
+15a2d 8b 552 60
+15ab8 28 553 60
+15ae0 5 554 60
+15ae5 16 550 60
+15afb 25 552 60
+15b20 5 557 60
+15b25 e 560 60
+15b33 7 561 60
+15b3a 5 563 60
+15b3f 6 564 60
+15b45 28 565 60
+15b6d 22 567 60
+15b8f a 568 60
+15b99 22 570 60
+15bbb a 571 60
+15bc5 22 573 60
+15be7 a 574 60
+15bf1 ba 576 60
+15cab 5 577 60
+15cb0 16 563 60
+15cc6 25 576 60
+15ceb 5 580 60
+15cf0 9 582 60
+15cf9 b 583 60
+FUNC 15d04 3d 0 dwarf2reader::LineInfo::Start()
+15d04 c 495 60
+15d10 b 496 60
+15d1b b 497 60
+15d26 19 498 60
+15d3f 2 499 60
+15d41 1 499 60
+FUNC 15d42 304 0 dwarf2reader::CompilationUnit::ProcessDIEs()
+15d42 11 435 60
+15d53 9 436 60
+15d5c 9 441 60
+15d65 17 445 60
+15d7c 8 446 60
+15d84 6 448 60
+15d8a 6c 453 60
+15df6 8 455 60
+15dfe 16 453 60
+15e14 3 455 60
+15e17 2f 453 60
+15e46 29 458 60
+15e6f 22 460 60
+15e91 a 462 60
+15e9b a 465 60
+15ea5 1e 466 60
+15ec3 13 467 60
+15ed6 2b 468 60
+15f01 18 472 60
+15f19 9 473 60
+15f22 42 474 60
+15f64 1e 475 60
+15f82 2a 477 60
+15fac b 480 60
+15fb7 1e 481 60
+15fd5 26 483 60
+15ffb 1d 455 60
+16018 24 485 60
+1603c a 486 60
+FUNC 16046 35f 0 dwarf2reader::CompilationUnit::Start()
+16046 18 249 60
+1605e 58 251 60
+160b6 35 252 60
+160eb 32 251 60
+1611d 2a 252 60
+16147 20 255 60
+16167 37 256 60
+1619e b 259 60
+161a9 f 264 60
+161b8 17 265 60
+161cf c 266 60
+161db a 268 60
+161e5 95 271 60
+1627a 11 276 60
+1628b b 279 60
+16296 58 282 60
+162ee 2f 283 60
+1631d 32 282 60
+1634f 14 284 60
+16363 1a 285 60
+1637d b 289 60
+16388 12 291 60
+1639a b 292 60
+163a5 1 292 60
+FUNC 163a6 3a 0 std::fill(unsigned char*, unsigned char*, unsigned char const&)
+163a6 c 573 61
+163b2 9 576 61
+163bb 23 577 61
+163de 2 578 61
+FUNC 163e0 33 0 std::__deque_buf_size(unsigned long)
+163e0 c 83 62
+163ec 27 84 62
+16413 1 84 62
+FUNC 16414 18 0 dwarf2reader::ByteReader::OffsetSize() const
+16414 c 38 63
+16420 c 38 63
+FUNC 1642c 18 0 dwarf2reader::ByteReader::AddressSize() const
+1642c c 41 63
+16438 c 41 63
+FUNC 16444 17 0 dwarf2reader::ByteReader::ReadOneByte(char const*) const
+16444 c 10 64
+16450 9 11 64
+16459 2 12 64
+1645b 1 12 64
+FUNC 1645c 63 0 dwarf2reader::ByteReader::ReadTwoBytes(char const*) const
+1645c c 14 64
+16468 d 15 64
+16475 e 16 64
+16483 b 17 64
+1648e 17 18 64
+164a5 18 20 64
+164bd 2 22 64
+164bf 1 22 64
+FUNC 164c0 98 0 dwarf2reader::ByteReader::ReadUnsignedLEB128(char const*, unsigned long*) const
+164c0 e 59 64
+164ce e 60 64
+164dc 7 61 64
+164e3 7 62 64
+164ea e 66 64
+164f8 5 67 64
+164fd 38 69 64
+16535 6 71 64
+1653b 8 65 64
+16543 8 75 64
+1654b 6 77 64
+16551 7 78 64
+FUNC 16558 ee 0 dwarf2reader::ByteReader::ReadSignedLEB128(char const*, unsigned long*) const
+16558 e 84 64
+16566 e 85 64
+16574 7 86 64
+1657b 7 87 64
+16582 e 91 64
+16590 5 92 64
+16595 44 93 64
+165d9 6 94 64
+165df 8 90 64
+165e7 14 97 64
+165fb 36 98 64
+16631 8 99 64
+16639 6 100 64
+1663f 7 101 64
+FUNC 16646 a2 0 dwarf2reader::ByteReader::ReadOffset(char const*) const
+16646 13 103 64
+16659 3f 104 64
+16698 4a 105 64
+166e2 6 106 64
+FUNC 166e8 a2 0 dwarf2reader::ByteReader::ReadAddress(char const*) const
+166e8 13 108 64
+166fb 3f 109 64
+1673a 4a 110 64
+16784 6 111 64
+FUNC 1678a 61 0 dwarf2reader::LineStateMachine::Reset(bool)
+1678a 12 12 65
+1679c 9 13 65
+167a5 11 14 65
+167b6 11 15 65
+167c7 a 16 65
+167d1 a 17 65
+167db 7 18 65
+167e2 7 19 65
+167e9 2 20 65
+167eb 1 20 65
+FUNC 167ec 20 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator!=(std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+167ec c 253 66
+167f8 14 254 66
+FUNC 1680c 25 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++(int)
+1680c c 226 66
+16818 8 228 66
+16820 c 229 66
+1682c 5 230 66
+16831 1 230 66
+FUNC 16832 16 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator->() const
+16832 c 215 66
+1683e a 216 66
+16848 c 190 67
+16854 a 190 67
+FUNC 1685e 13 0 std::auto_ptr<std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > > >::operator->() const
+1685e c 283 67
+1686a 7 286 67
+16871 1 286 67
+16872 c 65 68
+1687e 2 65 68
+16880 c 97 69
+1688c d 97 69
+16899 1 97 69
+1689a c 99 69
+168a6 14 100 69
+168ba c 97 69
+168c6 d 97 69
+168d3 1 97 69
+168d4 c 84 70
+168e0 17 85 70
+168f7 1 85 70
+FUNC 168f8 2d 0 std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> std::make_pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>(dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm)
+168f8 c 144 70
+16904 21 145 70
+16925 1 145 70
+16926 c 202 66
+16932 a 203 66
+FUNC 1693c 25 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::begin() const
+1693c c 588 70
+16948 19 589 66
+16961 1 589 66
+FUNC 16962 23 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::end() const
+16962 c 605 70
+1696e 17 606 66
+16985 1 606 66
+16986 c 65 68
+16992 2 65 68
+16994 c 72 68
+169a0 2 72 68
+169a2 c 97 69
+169ae d 97 69
+169bb 1 97 69
+169bc c 105 69
+169c8 d 105 69
+169d5 1 105 69
+169d6 c 105 69
+169e2 d 105 69
+169ef 1 105 69
+169f0 c 67 68
+169fc 2 67 68
+169fe c 99 69
+16a0a 14 100 69
+16a1e c 99 69
+16a2a 14 100 69
+16a3e c 129 62
+16a4a 30 131 62
+16a7a c 65 68
+16a86 2 65 68
+16a88 c 72 68
+16a94 2 72 68
+16a96 c 97 69
+16aa2 d 97 69
+16aaf 1 97 69
+16ab0 c 105 69
+16abc d 105 69
+16ac9 1 105 69
+16aca c 105 69
+16ad6 d 105 69
+16ae3 1 105 69
+16ae4 c 67 68
+16af0 2 67 68
+16af2 c 99 69
+16afe 14 100 69
+16b12 c 99 69
+16b1e 14 100 69
+FUNC 16b32 2b 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::get_allocator() const
+16b32 10 93 71
+16b42 1b 94 71
+16b5d 1 94 71
+16b6a 7 614 72
+16b71 1 614 72
+16b72 c 80 71
+16b7e d 80 71
+16b8b 1 80 71
+16b98 2 107 68
+FUNC 16b9a 2d 0 void std::_Destroy<unsigned char*, std::allocator<unsigned char> >(unsigned char*, unsigned char*, std::allocator<unsigned char>)
+16b9a c 171 73
+16ba6 2 173 73
+16ba8 12 174 73
+16bba b 173 73
+16bc5 2 174 73
+16bc7 1 174 73
+16bc8 c 84 71
+16bd4 2f 85 71
+16c03 2 86 71
+16c05 1 86 71
+16c06 c 96 71
+16c12 12 97 71
+16c24 2 98 71
+FUNC 16c26 1f 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_init()
+16c26 c 338 73
+16c32 8 340 66
+16c3a b 341 66
+16c45 1 341 66
+16c46 c 105 69
+16c52 d 105 69
+16c5f 1 105 69
+16c60 c 125 66
+16c6c a 126 66
+FUNC 16c76 25 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::begin()
+16c76 c 579 73
+16c82 19 580 66
+16c9b 1 580 66
+FUNC 16c9c 23 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::end()
+16c9c c 597 73
+16ca8 17 597 66
+16cbf 1 597 66
+16cc0 c 603 72
+16ccc c 603 72
+FUNC 16cd8 2b 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::begin() const
+16cd8 c 342 73
+16ce4 1f 343 71
+16d03 1 343 71
+FUNC 16d04 2c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::end() const
+16d04 c 360 73
+16d10 20 361 71
+16d3c 5 666 72
+16d41 1 666 72
+16d4f 31 759 72
+FUNC 16d80 3c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::size() const
+16d80 c 402 73
+16d8c 30 403 71
+16dbc c 603 72
+16dc8 c 603 72
+FUNC 16dd4 23 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::begin()
+16dd4 c 333 73
+16de0 17 334 71
+16df7 1 334 71
+16e04 33 654 72
+16e37 1 654 72
+FUNC 16e38 26 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::end()
+16e38 c 351 73
+16e44 1a 352 71
+16e6a 7 614 72
+16e71 1 614 72
+FUNC 16e72 42 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::operator[](unsigned long)
+16e72 c 494 73
+16e7e 36 495 71
+FUNC 16eb4 13 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::max_size() const
+16eb4 c 407 73
+16ec0 7 408 71
+16ec7 1 408 71
+16ed4 5 666 72
+16ed9 1 666 72
+16ee6 d 623 72
+16ef3 5 624 72
+16ef8 c 382 62
+16f04 d 382 62
+16f11 1 382 62
+FUNC 16f12 2b 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::get_allocator() const
+16f12 10 360 73
+16f22 1b 361 62
+16f3d 1 361 62
+FUNC 16f3e 2d 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::get_allocator() const
+16f3e 10 764 73
+16f4e 1d 765 62
+16f6b 1 765 62
+FUNC 16f6c 13 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator*() const
+16f6c c 134 73
+16f78 7 135 62
+16f7f 1 135 62
+16f8c 2 107 68
+16f8e c 129 62
+16f9a 30 131 62
+FUNC 16fca 2c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::end() const
+16fca 10 799 73
+16fda 1c 800 62
+FUNC 16ff6 2c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::begin() const
+16ff6 10 781 73
+17006 1c 782 62
+FUNC 17022 2e 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::end()
+17022 10 790 73
+17032 1e 791 62
+FUNC 17050 3c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_range_check(unsigned long) const
+17050 13 515 73
+17063 15 517 71
+17078 14 518 71
+FUNC 1708c 32 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::at(unsigned long)
+1708c c 534 73
+17098 12 536 71
+170aa 14 537 71
+170ca 2e 104 68
+170f8 c 84 71
+17104 2f 85 71
+17133 2 86 71
+17135 1 86 71
+17136 c 96 71
+17142 12 97 71
+17154 2 98 71
+17156 c 603 72
+17162 c 603 72
+FUNC 1716e 23 0 std::vector<unsigned char, std::allocator<unsigned char> >::begin()
+1716e c 333 73
+1717a 17 334 71
+17191 1 334 71
+1719e 27 654 72
+171c5 1 654 72
+FUNC 171c6 42 0 std::vector<unsigned char, std::allocator<unsigned char> >::operator[](unsigned long)
+171c6 c 494 73
+171d2 36 495 71
+FUNC 17208 26 0 std::vector<unsigned char, std::allocator<unsigned char> >::end()
+17208 c 351 73
+17214 1a 352 71
+1723a d 94 68
+17247 1 94 68
+FUNC 17248 2f 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate(unsigned char*, unsigned long)
+17248 c 120 73
+17254 6 122 71
+1725a 1d 123 71
+17277 1 123 71
+17278 c 108 71
+17284 3a 109 71
+172be c 188 71
+172ca 12 189 71
+172dc 2 190 71
+172de c 272 71
+172ea 4b 273 71
+17335 1 273 71
+17336 13 62 74
+17349 10 62 74
+17359 a 63 74
+17363 25 64 74
+17388 1a 66 74
+173a2 13 62 74
+173b5 10 62 74
+173c5 a 63 74
+173cf 25 64 74
+173f4 1a 66 74
+1740e c 188 71
+1741a 12 189 71
+1742c 2 190 71
+1743b 31 759 72
+1746c c 65 68
+17478 2 65 68
+1747a c 103 69
+17486 d 103 69
+17493 1 103 69
+FUNC 17494 2d 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::get_allocator() const
+17494 10 570 74
+174a4 1d 571 66
+174c1 1 571 66
+174ce 2e 104 68
+FUNC 174fc 20 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator!=(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+174fc c 172 74
+17508 14 173 66
+FUNC 1751c 1d 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++()
+1751c c 219 74
+17528 c 221 66
+17534 5 222 66
+17539 1 222 66
+FUNC 1753a 1d 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++()
+1753a c 138 74
+17546 c 140 66
+17552 5 141 66
+17557 1 141 66
+FUNC 17558 16 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator*() const
+17558 c 211 74
+17564 a 212 66
+FUNC 1756e 16 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator*() const
+1756e c 130 74
+1757a a 131 66
+FUNC 17584 20 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator==(std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+17584 c 249 74
+17590 14 250 66
+FUNC 175a4 35 0 bool __gnu_cxx::operator!=<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > const&)
+175a4 d 699 74
+175b1 28 700 72
+175d9 1 700 72
+FUNC 175da 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+175da c 171 74
+175e6 2 173 73
+175e8 1a 174 73
+17602 21 173 73
+17623 2 174 73
+17625 1 174 73
+17626 c 127 62
+17632 29 127 62
+1765b 1 127 62
+1765c c 388 62
+17668 41 389 62
+176a9 2 390 62
+176ab 1 390 62
+176b8 d 94 68
+176c5 1 94 68
+FUNC 176c6 20 0 bool std::operator==<unsigned long long, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+176c6 c 243 74
+176d2 14 244 62
+FUNC 176e6 26 0 bool std::operator!=<unsigned long long, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+176e6 c 256 74
+176f2 1a 257 62
+FUNC 1770c 1a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::_S_buffer_size()
+1770c c 106 74
+17718 e 107 62
+FUNC 17726 3e 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::_M_set_node(unsigned long long**)
+17726 d 229 74
+17733 9 231 62
+1773c b 232 62
+17747 1d 233 62
+FUNC 17764 50 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator++()
+17764 c 142 74
+17770 d 144 62
+1777d f 145 62
+1778c 18 147 62
+177a4 b 148 62
+177af 5 150 62
+FUNC 177b4 4b 0 void std::_Destroy<std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long> >(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long>)
+177b4 c 171 74
+177c0 2 173 73
+177c2 1a 174 73
+177dc 21 173 73
+177fd 2 174 73
+177ff 1 174 73
+FUNC 17800 50 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator--()
+17800 c 162 74
+1780c f 164 62
+1781b 18 166 62
+17833 b 167 62
+1783e d 169 62
+1784b 5 170 62
+FUNC 17850 39 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::back()
+17850 c 988 74
+1785c 15 990 62
+17871 b 991 62
+1787c d 992 62
+17889 1 992 62
+FUNC 1788a 19 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::top()
+1788a c 163 75
+17896 d 166 75
+178a3 1 166 75
+FUNC 178a4 66 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::difference_type std::operator-<unsigned long long, unsigned long long&, unsigned long long*, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+178a4 d 328 75
+178b1 59 333 62
+FUNC 1790a 26 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::size() const
+1790a c 840 75
+17916 1a 841 62
+1793c 36 662 72
+1797e 23 650 72
+179a1 1 650 72
+179a2 c 67 68
+179ae 2 67 68
+179b0 c 99 69
+179bc 14 100 69
+179d0 c 303 66
+179dc 12 304 66
+179ee 2 305 66
+179f0 c 326 66
+179fc 2f 327 66
+17a2b d 328 66
+17a38 c 457 66
+17a44 14 458 66
+17a58 c 211 74
+17a64 2d 211 74
+17a91 1 211 74
+17a9e 7 98 68
+17aa5 1 98 68
+17ab2 1d 85 68
+17acf 5 86 68
+17ad4 17 88 68
+17aeb 1 88 68
+FUNC 17aec 2a 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_allocate(unsigned long)
+17aec c 116 75
+17af8 1e 117 71
+17b22 d 94 68
+17b2f 1 94 68
+FUNC 17b30 34 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_deallocate_node(unsigned long long*)
+17b30 c 402 75
+17b3c 28 403 62
+FUNC 17b64 38 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_destroy_nodes(unsigned long long**, unsigned long long**)
+17b64 c 504 75
+17b70 8 506 62
+17b78 14 507 62
+17b8c e 506 62
+17b9a 2 507 62
+FUNC 17b9c 62 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_pop_back_aux()
+17b9c c 391 76
+17ba8 15 393 76
+17bbd 1b 394 76
+17bd8 f 395 76
+17be7 17 396 76
+FUNC 17bfe 4f 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::pop_back()
+17bfe c 1081 76
+17c0a 10 1083 62
+17c1a f 1086 62
+17c29 17 1087 62
+17c40 d 1090 62
+17c4d 1 1090 62
+FUNC 17c4e 19 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::pop()
+17c4e c 205 76
+17c5a d 208 75
+17c67 1 208 75
+17c68 c 72 68
+17c74 2 72 68
+17c76 c 105 69
+17c82 d 105 69
+17c8f 1 105 69
+17c90 c 603 72
+17c9c c 603 72
+FUNC 17ca8 2b 0 std::vector<unsigned char, std::allocator<unsigned char> >::begin() const
+17ca8 c 342 76
+17cb4 1f 343 71
+17cd3 1 343 71
+FUNC 17cd4 2c 0 std::vector<unsigned char, std::allocator<unsigned char> >::end() const
+17cd4 c 360 76
+17ce0 20 361 71
+17d0c 5 666 72
+17d11 1 666 72
+17d1f 28 759 72
+17d47 1 759 72
+FUNC 17d48 3c 0 std::vector<unsigned char, std::allocator<unsigned char> >::size() const
+17d48 c 402 76
+17d54 30 403 71
+17d90 d 623 72
+17d9d 5 624 72
+17dae 5 666 72
+17db3 1 666 72
+FUNC 17db4 35 0 bool __gnu_cxx::operator!=<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > const&, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > const&)
+17db4 d 699 76
+17dc1 28 700 72
+17de9 1 700 72
+FUNC 17dea 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<unsigned char> >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<unsigned char>)
+17dea c 171 76
+17df6 2 173 73
+17df8 1a 174 73
+17e12 21 173 73
+17e33 2 174 73
+17e35 1 174 73
+17e43 28 759 72
+17e6b 1 759 72
+17e78 2a 662 72
+FUNC 17ea2 13 0 std::vector<unsigned char, std::allocator<unsigned char> >::max_size() const
+17ea2 c 407 76
+17eae 7 408 71
+17eb5 1 408 71
+17ec2 16 650 72
+17ee4 7 98 68
+17eeb 1 98 68
+17ef8 1d 85 68
+17f15 5 86 68
+17f1a 10 88 68
+FUNC 17f2a 29 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_get_node()
+17f2a c 311 76
+17f36 1d 312 66
+17f53 1 312 66
+FUNC 17f54 5f 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_create_node(std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+17f54 d 435 76
+17f61 e 437 66
+17f6f 3c 440 66
+17fab 8 447 66
+17fb3 1 447 66
+FUNC 17fb4 35 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_insert(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+17fb4 c 1149 76
+17fc0 15 1151 66
+17fd5 14 1152 66
+17fe9 1 1152 66
+FUNC 17fea 52 0 void std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_insert_dispatch<std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, __false_type)
+17fea c 1126 66
+17ff6 2 1128 66
+17ff8 21 1129 66
+18019 21 1128 66
+1803a 2 1129 66
+FUNC 1803c 36 0 void std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::insert<std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+1803c c 838 66
+18048 2a 842 66
+18072 e 491 66
+18080 32 492 66
+180b2 64 493 66
+18116 c 211 74
+18122 3d 211 74
+1815f 1 211 74
+1816d 5c 104 68
+181c9 1 104 68
+FUNC 181ca 31 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::push_back(std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+181ca c 772 76
+181d6 25 773 66
+181fb 1 773 66
+FUNC 181fc 69 0 void std::_Construct<dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev const&)
+181fc d 77 76
+18209 5c 81 73
+18265 1 81 73
+18272 7 98 68
+18279 1 98 68
+18286 1d 85 68
+182a3 5 86 68
+182a8 10 88 68
+182b8 c 65 68
+182c4 2 65 68
+182c6 c 103 69
+182d2 d 103 69
+182df 1 103 69
+FUNC 182e0 4d 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_get_map_allocator() const
+182e0 11 394 76
+182f1 3c 395 62
+1832d 1 395 62
+FUNC 1832e 75 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_allocate_map(unsigned long)
+1832e d 406 76
+1833b 68 407 62
+183a3 1 407 62
+FUNC 183a4 47 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_deallocate_map(unsigned long long**, unsigned long)
+183a4 c 410 76
+183b0 3b 411 62
+183eb 1 411 62
+183ec c 424 62
+183f8 9 426 62
+18401 22 428 62
+18423 2b 430 62
+1844e c 714 62
+1845a 70 715 62
+184ca c 111 75
+184d6 d 111 75
+184e3 1 111 75
+184e4 c 259 67
+184f0 26 259 67
+18522 7 98 68
+18529 1 98 68
+18536 1d 85 68
+18553 5 86 68
+18558 10 88 68
+FUNC 18568 33 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_allocate_node()
+18568 c 398 76
+18574 27 399 62
+1859b 1 399 62
+FUNC 1859c 82 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_create_nodes(unsigned long long**, unsigned long long**)
+1859c d 486 76
+185a9 8 491 62
+185b1 12 492 62
+185c3 13 491 62
+185d6 b 494 62
+185e1 19 496 62
+185fa b 497 62
+18605 13 494 62
+18618 6 497 62
+FUNC 1861e 17b 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_initialize_map(unsigned long)
+1861e d 447 76
+1862b 1e 450 62
+18649 2a 452 62
+18673 1c 454 62
+1868f 19 462 62
+186a8 c 463 62
+186b4 1e 466 62
+186d2 b 467 62
+186dd 1e 469 62
+186fb 9 470 62
+18704 a 471 62
+1870e b 472 62
+18719 13 467 62
+1872c 15 475 62
+18741 18 476 62
+18759 c 477 62
+18765 34 478 62
+18799 1 478 62
+1879a d 366 62
+187a7 12 367 62
+187b9 39 368 62
+187f2 c 645 62
+187fe 1c 646 62
+FUNC 1881a 4d 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char const&)
+1881a c 539 61
+18826 9 541 61
+1882f 2 542 61
+18831 13 543 61
+18844 21 542 61
+18865 2 543 61
+18867 1 543 61
+FUNC 18868 2b 0 void std::fill<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char const&)
+18868 c 560 76
+18874 4 567 61
+18878 1b 568 61
+18893 1 568 61
+FUNC 18894 6a 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+18894 d 1157 76
+188a1 b 1159 66
+188ac 6 1160 66
+188b2 35 1161 66
+188e7 17 1162 66
+FUNC 188fe 37 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+188fe c 95 77
+1890a 14 97 77
+1891e 12 98 77
+18930 5 99 77
+18935 1 99 77
+FUNC 18936 3e 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+18936 c 883 77
+18942 2 885 66
+18944 15 886 66
+18959 16 885 66
+1896f 5 887 66
+FUNC 18974 129 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::operator=(std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+18974 e 120 77
+18982 c 122 77
+1898e e 124 77
+1899c e 125 77
+189aa e 126 77
+189b8 e 127 77
+189c6 2 128 77
+189c8 20 130 77
+189e8 5a 128 77
+18a42 16 131 77
+18a58 1b 132 77
+18a73 20 134 77
+18a93 a 136 77
+18a9d 1 136 77
+FUNC 18a9e 4c 0 dwarf2reader::CompilationUnit::Abbrev::operator=(dwarf2reader::CompilationUnit::Abbrev const&)
+18a9e c 211 77
+18aaa 40 211 74
+FUNC 18aea 52 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy<false, std::random_access_iterator_tag>::copy<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18aea c 280 61
+18af6 1a 283 61
+18b10 12 285 61
+18b22 4 286 61
+18b26 6 287 61
+18b2c b 283 61
+18b37 5 289 61
+FUNC 18b3c 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18b3c c 307 77
+18b48 4 315 61
+18b4c 1b 317 61
+18b67 1 317 61
+18b76 56 354 61
+18bd8 4 384 61
+18bdc 4 385 61
+18be0 1b 387 61
+18bfb 1 387 61
+FUNC 18bfc ac 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::erase(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >)
+18bfc d 122 78
+18c09 26 124 78
+18c2f 43 125 78
+18c72 2e 126 78
+18ca0 8 127 78
+FUNC 18ca8 54 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18ca8 c 408 61
+18cb4 1a 411 61
+18cce 1e 412 61
+18cec b 411 61
+18cf7 5 413 61
+FUNC 18cfc 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18cfc c 432 78
+18d08 4 440 61
+18d0c 1b 443 61
+18d27 1 443 61
+18d36 56 482 61
+18d98 4 514 61
+18d9c 4 515 61
+18da0 1b 517 61
+18dbb 1 517 61
+FUNC 18dbc 4d 0 void std::__fill<false>::fill<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+18dbc c 526 61
+18dc8 2 528 61
+18dca 1c 529 61
+18de6 21 528 61
+18e07 2 529 61
+18e09 1 529 61
+FUNC 18e0a 2b 0 void std::fill<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+18e0a c 560 78
+18e16 4 567 61
+18e1a 1b 568 61
+18e35 1 568 61
+FUNC 18e36 3f 0 unsigned char* std::__copy<true, std::random_access_iterator_tag>::copy<unsigned char>(unsigned char const*, unsigned char const*, unsigned char*)
+18e36 c 298 61
+18e42 22 300 61
+18e64 11 301 61
+18e75 1 301 61
+FUNC 18e76 2b 0 unsigned char* std::__copy_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+18e76 c 307 78
+18e82 4 315 61
+18e86 1b 317 61
+18ea1 1 317 61
+18eb0 56 354 61
+18f12 4 384 61
+18f16 4 385 61
+18f1a 1b 387 61
+18f35 1 387 61
+FUNC 18f36 a0 0 std::vector<unsigned char, std::allocator<unsigned char> >::erase(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
+18f36 d 122 78
+18f43 26 124 78
+18f69 43 125 78
+18fac 22 126 78
+18fce 8 127 78
+18fe2 7 98 68
+18fe9 1 98 68
+18ff6 1d 85 68
+19013 5 86 68
+19018 d 88 68
+19025 1 88 68
+FUNC 19026 2a 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long)
+19026 c 116 78
+19032 1e 117 71
+1905c 1b 74 79
+19077 1 74 79
+19084 23 113 79
+190a7 1 113 79
+190b4 1b 254 79
+190cf 1 254 79
+FUNC 190d0 19 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*)
+190d0 c 106 79
+190dc d 107 73
+190e9 1 107 73
+FUNC 190ea 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __false_type)
+190ea c 119 79
+190f6 2 121 73
+190f8 13 122 73
+1910b 21 121 73
+1912c 2 122 73
+FUNC 1912e 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >)
+1912e c 148 79
+1913a 1c 155 73
+FUNC 19156 8d 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type)
+19156 d 188 79
+19163 6 190 79
+19169 2 193 79
+1916b 1c 194 79
+19187 1b 193 79
+191a2 b 196 79
+191ad 12 198 79
+191bf b 199 79
+191ca 13 196 79
+191dd 6 199 79
+191e3 1 199 79
+FUNC 191e4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+191e4 c 214 79
+191f0 23 218 79
+19213 1 218 79
+FUNC 19214 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19214 c 308 79
+19220 1b 310 79
+1923b 1 310 79
+19249 6 82 79
+1924f 2 85 79
+19251 24 86 79
+19275 2c 85 79
+192a1 b 87 79
+192ac b 89 79
+192b7 12 91 79
+192c9 b 92 79
+192d4 13 89 79
+192e7 9 92 79
+192fc 23 113 79
+1931f 1 113 79
+1932c 1b 254 79
+19347 1 254 79
+FUNC 19348 409 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_insert_aux(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+19348 14 249 79
+1935c 14 251 78
+19370 22 253 78
+19392 f 255 78
+193a1 12 256 78
+193b3 55 257 78
+19408 4b 260 78
+19453 e 264 78
+19461 15 265 78
+19476 e 266 78
+19484 1d 271 78
+194a1 8 272 78
+194a9 e 273 78
+194b7 27 275 78
+194de 6 276 78
+194e4 55 279 78
+19539 25 284 78
+1955e b 285 78
+19569 4f 286 78
+195b8 3 284 78
+195bb 13 279 78
+195ce e 286 78
+195dc 4d 298 78
+19629 36 299 78
+1965f 12 302 78
+19671 13 303 78
+19684 2e 304 78
+196b2 13 286 78
+196c5 b 292 78
+196d0 39 294 78
+19709 23 295 78
+1972c b 296 78
+19737 13 292 78
+1974a 7 304 78
+19751 1 304 78
+FUNC 19752 70 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::push_back(dwarf2reader::CompilationUnit::Abbrev const&)
+19752 c 602 79
+1975e 10 604 71
+1976e 1e 606 71
+1978c 11 607 71
+1979d 25 610 71
+FUNC 197c2 50 0 unsigned char* std::__copy_backward<true, std::random_access_iterator_tag>::copy_b<unsigned char>(unsigned char const*, unsigned char const*, unsigned char*)
+197c2 d 422 61
+197cf f 424 61
+197de 24 425 61
+19802 10 426 61
+FUNC 19812 2b 0 unsigned char* std::__copy_backward_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+19812 c 432 79
+1981e 4 440 61
+19822 1b 443 61
+1983d 1 443 61
+1984c 56 482 61
+198ae 4 514 61
+198b2 4 515 61
+198b6 1b 517 61
+198d1 1 517 61
+FUNC 198d2 32 0 unsigned char* std::fill_n<unsigned long>(unsigned char*, unsigned long, unsigned char const&)
+198d2 c 647 79
+198de 1e 649 61
+198fc 8 650 61
+FUNC 19904 27 0 void std::__uninitialized_fill_n_aux<unsigned char*, unsigned long, unsigned char>(unsigned char*, unsigned long, unsigned char const&, __true_type)
+19904 c 182 79
+19910 1b 183 79
+1992b 1 183 79
+FUNC 1992c 2f 0 void std::uninitialized_fill_n<unsigned char*, unsigned long, unsigned char>(unsigned char*, unsigned long, unsigned char const&)
+1992c c 214 79
+19938 23 218 79
+1995b 1 218 79
+FUNC 1995c 27 0 void std::__uninitialized_fill_n_a<unsigned char*, unsigned long, unsigned char, unsigned char>(unsigned char*, unsigned long, unsigned char const&, std::allocator<unsigned char>)
+1995c c 308 79
+19968 1b 310 79
+19983 1 310 79
+FUNC 19984 27 0 void std::__destroy_aux<dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+19984 c 119 79
+19990 2 121 73
+19992 b 122 73
+1999d c 121 73
+199a9 2 122 73
+199ab 1 122 73
+FUNC 199ac 28 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+199ac c 148 79
+199b8 1c 155 73
+FUNC 199d4 88 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+199d4 d 80 79
+199e1 6 82 79
+199e7 2 85 79
+199e9 12 86 79
+199fb 12 85 79
+19a0d b 87 79
+19a18 b 89 79
+19a23 12 91 79
+19a35 b 92 79
+19a40 13 89 79
+19a53 9 92 79
+FUNC 19a5c 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+19a5c c 108 79
+19a68 23 113 79
+19a8b 1 113 79
+FUNC 19a8c 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19a8c c 252 79
+19a98 1b 254 79
+19ab3 1 254 79
+FUNC 19ab4 7e 0 void std::__uninitialized_fill_n_aux<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type)
+19ab4 d 188 79
+19ac1 6 190 79
+19ac7 2 193 79
+19ac9 12 194 79
+19adb 16 193 79
+19af1 b 196 79
+19afc 12 198 79
+19b0e b 199 79
+19b19 13 196 79
+19b2c 6 199 79
+FUNC 19b32 2f 0 void std::uninitialized_fill_n<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+19b32 c 214 79
+19b3e 23 218 79
+19b61 1 218 79
+FUNC 19b62 27 0 void std::__uninitialized_fill_n_a<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19b62 c 308 79
+19b6e 1b 310 79
+19b89 1 310 79
+FUNC 19b8a a5 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+19b8a d 80 79
+19b97 6 82 79
+19b9d 2 85 79
+19b9f 1a 86 79
+19bb9 27 85 79
+19be0 b 87 79
+19beb b 89 79
+19bf6 12 91 79
+19c08 b 92 79
+19c13 13 89 79
+19c26 9 92 79
+19c2f 1 92 79
+FUNC 19c30 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*)
+19c30 c 108 79
+19c3c 23 113 79
+19c5f 1 113 79
+FUNC 19c60 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19c60 c 252 79
+19c6c 1b 254 79
+19c87 1 254 79
+FUNC 19c88 5f8 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_fill_insert(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+19c88 15 311 79
+19c9d b 313 78
+19ca8 2a 315 78
+19cd2 12 318 78
+19ce4 23 319 78
+19d07 15 320 78
+19d1c c 321 78
+19d28 5a 323 78
+19d82 1c 327 78
+19d9e 35 328 78
+19dd3 16 323 78
+19de9 30 330 78
+19e19 10 343 78
+19e29 48 334 78
+19e71 21 338 78
+19e92 3d 339 78
+19ecf 13 334 78
+19ee2 b 339 78
+19eed 1c 342 78
+19f09 1e 343 78
+19f27 13 339 78
+19f3a 24 343 78
+19f5e e 348 78
+19f6c 1e 349 78
+19f8a e 350 78
+19f98 1d 353 78
+19fb5 8 354 78
+19fbd e 355 78
+19fcb 27 357 78
+19ff2 6 358 78
+19ff8 4d 361 78
+1a045 40 365 78
+1a085 18 367 78
+1a09d 44 368 78
+1a0e1 3 365 78
+1a0e4 19 361 78
+1a0fd 13 365 78
+1a110 e 368 78
+1a11e 3e 379 78
+1a15c 36 381 78
+1a192 12 384 78
+1a1a4 13 385 78
+1a1b7 2e 386 78
+1a1e5 e 368 78
+1a1f3 b 372 78
+1a1fe 39 374 78
+1a237 23 376 78
+1a25a b 377 78
+1a265 13 372 78
+1a278 8 386 78
+FUNC 1a280 2e 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::insert(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+1a280 c 657 79
+1a28c 22 658 71
+FUNC 1a2ae ab 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::resize(unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+1a2ae d 422 79
+1a2bb 15 424 71
+1a2d0 48 425 71
+1a318 41 427 71
+1a359 1 427 71
+FUNC 1a35a 63 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::resize(unsigned long)
+1a35a d 441 79
+1a367 56 442 71
+1a3bd 1 442 71
+FUNC 1a3be 13 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::operator*() const
+1a3be c 134 79
+1a3ca 7 135 62
+1a3d1 1 135 62
+FUNC 1a3d2 3f 0 unsigned long long** std::__copy<true, std::random_access_iterator_tag>::copy<unsigned long long*>(unsigned long long* const*, unsigned long long* const*, unsigned long long**)
+1a3d2 c 298 61
+1a3de 22 300 61
+1a400 11 301 61
+1a411 1 301 61
+FUNC 1a412 2b 0 unsigned long long** std::__copy_aux<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a412 c 307 79
+1a41e 4 315 61
+1a422 1b 317 61
+1a43d 1 317 61
+FUNC 1a43e 27 0 unsigned long long** std::__copy_normal<false, false>::copy_n<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a43e c 325 61
+1a44a 1b 326 61
+1a465 1 326 61
+FUNC 1a466 2f 0 unsigned long long** std::copy<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a466 c 376 79
+1a472 4 384 61
+1a476 4 385 61
+1a47a 1b 387 61
+1a495 1 387 61
+FUNC 1a496 60 0 unsigned long long** std::__copy_backward<true, std::random_access_iterator_tag>::copy_b<unsigned long long*>(unsigned long long* const*, unsigned long long* const*, unsigned long long**)
+1a496 d 422 61
+1a4a3 12 424 61
+1a4b5 2e 425 61
+1a4e3 13 426 61
+FUNC 1a4f6 2b 0 unsigned long long** std::__copy_backward_aux<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a4f6 c 432 79
+1a502 4 440 61
+1a506 1b 443 61
+1a521 1 443 61
+FUNC 1a522 27 0 unsigned long long** std::__copy_backward_normal<false, false>::copy_b_n<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a522 c 451 61
+1a52e 1b 452 61
+1a549 1 452 61
+FUNC 1a54a 2f 0 unsigned long long** std::copy_backward<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a54a c 504 79
+1a556 4 514 61
+1a55a 4 515 61
+1a55e 1b 517 61
+1a579 1 517 61
+FUNC 1a57a 1df 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_reallocate_map(unsigned long, bool)
+1a57a 13 723 79
+1a58d 1b 726 76
+1a5a8 9 727 76
+1a5b1 13 730 76
+1a5c4 39 732 76
+1a5fd b 735 76
+1a608 27 736 76
+1a62f 2f 740 76
+1a65e 26 748 76
+1a684 15 750 76
+1a699 36 751 76
+1a6cf 22 753 76
+1a6f1 1e 756 76
+1a70f 8 758 76
+1a717 9 759 76
+1a720 15 762 76
+1a735 24 763 76
+1a759 1 763 76
+FUNC 1a75a 59 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_reserve_map_at_back(unsigned long)
+1a75a e 1443 79
+1a768 2a 1445 62
+1a792 21 1447 62
+1a7b3 1 1447 62
+FUNC 1a7b4 8c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_push_back_aux(unsigned long long const&)
+1a7b4 c 345 79
+1a7c0 e 347 76
+1a7ce 13 348 76
+1a7e1 18 349 76
+1a7f9 1e 352 76
+1a817 1b 353 76
+1a832 c 355 76
+1a83e 2 360 76
+FUNC 1a840 62 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::push_back(unsigned long long const&)
+1a840 c 1039 79
+1a84c 13 1041 62
+1a85f 1e 1044 62
+1a87d 11 1045 62
+1a88e 14 1048 62
+FUNC 1a8a2 20 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::push(unsigned long long const&)
+1a8a2 c 190 79
+1a8ae 14 191 75
+FUNC 1a8c2 27 0 unsigned char* std::__copy_normal<false, false>::copy_n<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a8c2 c 325 61
+1a8ce 1b 326 61
+1a8e9 1 326 61
+FUNC 1a8ea 2f 0 unsigned char* std::copy<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a8ea c 376 79
+1a8f6 4 384 61
+1a8fa 4 385 61
+1a8fe 1b 387 61
+1a919 1 387 61
+FUNC 1a91a 27 0 unsigned char* std::__uninitialized_copy_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*, __true_type)
+1a91a c 73 79
+1a926 1b 74 79
+1a941 1 74 79
+FUNC 1a942 2f 0 unsigned char* std::uninitialized_copy<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a942 c 108 79
+1a94e 23 113 79
+1a971 1 113 79
+FUNC 1a972 27 0 unsigned char* std::__uninitialized_copy_a<unsigned char*, unsigned char*, unsigned char>(unsigned char*, unsigned char*, unsigned char*, std::allocator<unsigned char>)
+1a972 c 252 79
+1a97e 1b 254 79
+1a999 1 254 79
+FUNC 1a99a 40 0 unsigned char* std::__copy_normal<true, false>::copy_n<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1a99a d 334 61
+1a9a7 33 335 61
+FUNC 1a9da 2f 0 unsigned char* std::copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1a9da c 376 79
+1a9e6 4 384 61
+1a9ea 4 385 61
+1a9ee 1b 387 61
+1aa09 1 387 61
+FUNC 1aa0a 27 0 unsigned char* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, __true_type)
+1aa0a c 73 79
+1aa16 1b 74 79
+1aa31 1 74 79
+FUNC 1aa32 2f 0 unsigned char* std::uninitialized_copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1aa32 c 108 79
+1aa3e 23 113 79
+1aa61 1 113 79
+FUNC 1aa62 27 0 unsigned char* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, std::allocator<unsigned char>)
+1aa62 c 252 79
+1aa6e 1b 254 79
+1aa89 1 254 79
+1aa96 9 616 61
+1aa9f 2 617 61
+1aaa1 13 618 61
+1aab4 16 617 61
+1aaca 5 619 61
+1aacf 1 619 61
+1aadc 4 641 61
+1aae0 1b 642 61
+1aafb 1 642 61
+FUNC 1aafc 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&, __true_type)
+1aafc c 182 79
+1ab08 1b 183 79
+1ab23 1 183 79
+FUNC 1ab24 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1ab24 c 214 79
+1ab30 23 218 79
+1ab53 1 218 79
+FUNC 1ab54 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&, std::allocator<unsigned char>)
+1ab54 c 308 79
+1ab60 1b 310 79
+1ab7b 1 310 79
+FUNC 1ab7c 45a 0 std::vector<unsigned char, std::allocator<unsigned char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1ab7c 14 311 79
+1ab90 b 313 78
+1ab9b 21 315 78
+1abbc 9 318 78
+1abc5 23 319 78
+1abe8 15 320 78
+1abfd c 321 78
+1ac09 4e 323 78
+1ac57 11 327 78
+1ac68 30 328 78
+1ac98 35 330 78
+1accd 48 334 78
+1ad15 14 338 78
+1ad29 43 339 78
+1ad6c 11 342 78
+1ad7d 1e 343 78
+1ad9b e 348 78
+1ada9 1e 349 78
+1adc7 e 350 78
+1add5 1d 353 78
+1adf2 8 354 78
+1adfa e 355 78
+1ae08 27 357 78
+1ae2f 6 358 78
+1ae35 4d 361 78
+1ae82 40 365 78
+1aec2 18 367 78
+1aeda 4d 368 78
+1af27 3e 379 78
+1af65 2d 381 78
+1af92 12 384 78
+1afa4 13 385 78
+1afb7 1f 386 78
+FUNC 1afd6 2e 0 std::vector<unsigned char, std::allocator<unsigned char> >::insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1afd6 c 657 79
+1afe2 22 658 71
+FUNC 1b004 ab 0 std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long, unsigned char const&)
+1b004 d 422 79
+1b011 15 424 71
+1b026 48 425 71
+1b06e 41 427 71
+1b0af 1 427 71
+FUNC 1b0b0 2b 0 std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long)
+1b0b0 c 441 79
+1b0bc 1f 442 71
+1b0db 1 442 71
+FUNC 1b0dc 1a 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::_S_buffer_size()
+1b0dc c 106 79
+1b0e8 e 107 62
+FUNC 1b0f6 66 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::difference_type std::operator-<unsigned long long, unsigned long long const&, unsigned long long const*, unsigned long long const&, unsigned long long const*>(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*> const&, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*> const&)
+1b0f6 d 328 79
+1b103 59 333 62
+FUNC 1b15c 3e 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::_M_set_node(unsigned long long**)
+1b15c d 229 79
+1b169 9 231 62
+1b172 b 232 62
+1b17d 1d 233 62
+FUNC 1b19a 50 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::operator++()
+1b19a c 142 79
+1b1a6 d 144 62
+1b1b3 f 145 62
+1b1c2 18 147 62
+1b1da b 148 62
+1b1e5 5 150 62
+FUNC 1b1ea 84 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy<false, std::random_access_iterator_tag>::copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b1ea e 280 61
+1b1f8 17 283 61
+1b20f 20 285 61
+1b22f b 286 61
+1b23a b 287 61
+1b245 b 283 61
+1b250 1e 289 61
+FUNC 1b26e 7e 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy_aux<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b26e 11 307 79
+1b27f 4 315 61
+1b283 69 317 61
+FUNC 1b2ec 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy_normal<false, false>::copy_n<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b2ec 11 325 61
+1b2fd 69 326 61
+FUNC 1b366 82 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b366 11 376 79
+1b377 4 384 61
+1b37b 4 385 61
+1b37f 69 387 61
+FUNC 1b3e8 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__uninitialized_copy_aux<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, __true_type)
+1b3e8 11 73 79
+1b3f9 69 74 79
+FUNC 1b462 82 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::uninitialized_copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b462 11 108 79
+1b473 71 113 79
+FUNC 1b4e4 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__uninitialized_copy_a<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, unsigned long long>(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long>)
+1b4e4 11 252 79
+1b4f5 69 254 79
+1b55e 10 679 62
+1b56e 64 680 62
+1b5d2 e8 681 62
+1b6ba c 143 75
+1b6c6 14 144 75
+1b6da 6 144 75
+FUNC 1b6e0 4d 0 __eprintf
+1b6e0 6 1826 80
+1b6e6 3 1832 80
+1b6e9 c 1826 80
+1b6f5 29 1832 80
+1b71e a 1837 80
+1b728 5 1838 80
+1b72d e8d3 1838 80
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h b/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h
new file mode 100644
index 0000000000..1e4b752e51
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h
@@ -0,0 +1,47 @@
+// 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.
+
+#ifndef CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
+#define CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
+
+#include <sys/ucontext.h>
+
+// The purpose of this file is to work around the fact that ucontext_t's
+// uc_mcontext member is an mcontext_t rather than an mcontext64_t on ARM64.
+#if defined(__aarch64__)
+// <sys/ucontext.h> doesn't include the below file.
+#include <sys/_types/_ucontext64.h>
+typedef ucontext64_t breakpad_ucontext_t;
+#define breakpad_uc_mcontext uc_mcontext64
+#else
+typedef ucontext_t breakpad_ucontext_t;
+#define breakpad_uc_mcontext uc_mcontext
+#endif // defined(__aarch64__)
+
+#endif // CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm b/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm
new file mode 100644
index 0000000000..2ea103c694
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm
@@ -0,0 +1,217 @@
+// Copyright (c) 2009, 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.
+//
+// BreakpadFramework_Test.mm
+// Test case file for Breakpad.h/mm.
+//
+
+#import "GTMSenTestCase.h"
+#import "Breakpad.h"
+
+#include <mach/mach.h>
+
+@interface BreakpadFramework_Test : GTMTestCase {
+ @private
+ int last_exception_code_;
+ int last_exception_type_;
+ mach_port_t last_exception_thread_;
+ // We're not using Obj-C BOOL because we need to interop with
+ // Breakpad's callback.
+ bool shouldHandleException_;
+}
+
+// This method is used by a callback used by test cases to determine
+// whether to return true or false to Breakpad when handling an
+// exception.
+- (bool)shouldHandleException;
+// This method returns a minimal dictionary that has what
+// Breakpad needs to initialize.
+- (NSMutableDictionary *)breakpadInitializationDictionary;
+// This method is used by the exception handling callback
+// to communicate to test cases the properites of the last
+// exception.
+- (void)setLastExceptionType:(int)type andCode:(int)code
+ andThread:(mach_port_t)thread;
+@end
+
+// Callback for Breakpad exceptions
+bool myBreakpadCallback(int exception_type,
+ int exception_code,
+ mach_port_t crashing_thread,
+ void *context);
+
+bool myBreakpadCallback(int exception_type,
+ int exception_code,
+ mach_port_t crashing_thread,
+ void *context) {
+ BreakpadFramework_Test *testCaseClass =
+ (BreakpadFramework_Test *)context;
+ [testCaseClass setLastExceptionType:exception_type
+ andCode:exception_code
+ andThread:crashing_thread];
+ bool shouldHandleException =
+ [testCaseClass shouldHandleException];
+ NSLog(@"Callback returning %d", shouldHandleException);
+ return shouldHandleException;
+}
+const int kNoLastExceptionCode = -1;
+const int kNoLastExceptionType = -1;
+const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL;
+
+@implementation BreakpadFramework_Test
+- (void) initializeExceptionStateVariables {
+ last_exception_code_ = kNoLastExceptionCode;
+ last_exception_type_ = kNoLastExceptionType;
+ last_exception_thread_ = kNoLastExceptionThread;
+}
+
+- (NSMutableDictionary *)breakpadInitializationDictionary {
+ NSMutableDictionary *breakpadParams =
+ [NSMutableDictionary dictionaryWithCapacity:3];
+
+ [breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT];
+ [breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION];
+ [breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL];
+ return breakpadParams;
+}
+
+- (bool)shouldHandleException {
+ return shouldHandleException_;
+}
+
+- (void)setLastExceptionType:(int)type
+ andCode:(int)code
+ andThread:(mach_port_t)thread {
+ last_exception_type_ = type;
+ last_exception_code_ = code;
+ last_exception_thread_ = thread;
+}
+
+// Test that the parameters mark required actually enable Breakpad to
+// be initialized.
+- (void)testBreakpadInstantiationWithRequiredParameters {
+ BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]);
+ STAssertNotNULL(b, @"BreakpadCreate failed with required parameters");
+ BreakpadRelease(b);
+}
+
+// Test that Breakpad fails to initialize cleanly when required
+// parameters are not present.
+- (void)testBreakpadInstantiationWithoutRequiredParameters {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ // Skip setting version, so that BreakpadCreate fails.
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION];
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+
+ breakpadDictionary = [self breakpadInitializationDictionary];
+ // Now test with no product
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT];
+ b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+
+ breakpadDictionary = [self breakpadInitializationDictionary];
+ // Now test with no URL
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_URL];
+ b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+ BreakpadRelease(b);
+}
+
+// Test to ensure that when we call BreakpadAddUploadParameter,
+// it's added to the dictionary correctly(this test depends on
+// some internal details of Breakpad, namely, the special prefix
+// that it uses to figure out which key/value pairs to upload).
+- (void)testAddingBreakpadServerVariable {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
+
+ BreakpadAddUploadParameter(b,
+ @"key",
+ @"value");
+
+ // Test that it did not add the key/value directly, e.g. without
+ // prepending the key with the prefix.
+ STAssertNil(BreakpadKeyValue(b, @"key"),
+ @"AddUploadParameter added key directly to dictionary"
+ " instead of prepending it!");
+
+ NSString *prependedKeyname =
+ [@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"];
+
+ STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname),
+ @"value",
+ @"Calling BreakpadAddUploadParameter did not prepend "
+ "key name");
+ BreakpadRelease(b);
+}
+
+// Test that when we do on-demand minidump generation,
+// the exception code/type/thread are set properly.
+- (void)testFilterCallbackReturnsFalse {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
+ BreakpadSetFilterCallback(b, &myBreakpadCallback, self);
+
+ // This causes the callback to return false, meaning
+ // Breakpad won't take the exception
+ shouldHandleException_ = false;
+
+ [self initializeExceptionStateVariables];
+ STAssertEquals(last_exception_type_, kNoLastExceptionType,
+ @"Last exception type not initialized correctly.");
+ STAssertEquals(last_exception_code_, kNoLastExceptionCode,
+ @"Last exception code not initialized correctly.");
+ STAssertEquals(last_exception_thread_, kNoLastExceptionThread,
+ @"Last exception thread is not initialized correctly.");
+
+ // Cause Breakpad's exception handler to be invoked.
+ BreakpadGenerateAndSendReport(b);
+
+ STAssertEquals(last_exception_type_, 0,
+ @"Last exception type is not 0 for on demand");
+ STAssertEquals(last_exception_code_, 0,
+ @"Last exception code is not 0 for on demand");
+ STAssertEquals(last_exception_thread_, mach_thread_self(),
+ @"Last exception thread is not mach_thread_self() "
+ "for on demand");
+}
+
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc
new file mode 100644
index 0000000000..0164f4a298
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc
@@ -0,0 +1,398 @@
+// Copyright (c) 2010, 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.
+//
+// crash_generation_server_test.cc
+// Unit tests for CrashGenerationServer
+
+#include <dirent.h>
+#include <glob.h>
+#include <stdint.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/crash_generation/client_info.h"
+#include "client/mac/crash_generation/crash_generation_client.h"
+#include "client/mac/crash_generation/crash_generation_server.h"
+#include "client/mac/handler/exception_handler.h"
+#include "client/mac/tests/spawn_child_process.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using google_breakpad::AutoTempDir;
+using google_breakpad::ClientInfo;
+using google_breakpad::CrashGenerationClient;
+using google_breakpad::CrashGenerationServer;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpModule;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MinidumpThreadList;
+using testing::Test;
+using namespace google_breakpad_test;
+
+class CrashGenerationServerTest : public Test {
+public:
+ // The port name to receive messages on
+ char mach_port_name[128];
+ // Filename of the last dump that was generated
+ string last_dump_name;
+ // PID of the child process
+ pid_t child_pid;
+ // A temp dir
+ AutoTempDir temp_dir;
+ // Counter just to ensure that we don't hit the same port again
+ static int i;
+ bool filter_callback_called;
+
+ void SetUp() {
+ sprintf(mach_port_name,
+ "com.google.breakpad.ServerTest.%d.%d", getpid(),
+ CrashGenerationServerTest::i++);
+ child_pid = (pid_t)-1;
+ filter_callback_called = false;
+ }
+};
+int CrashGenerationServerTest::i = 0;
+
+// Test that starting and stopping a server works
+TEST_F(CrashGenerationServerTest, testStartStopServer) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ NULL, // dump callback
+ NULL, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ false, // generate dumps
+ ""); // dump path
+ ASSERT_TRUE(server.Start());
+ ASSERT_TRUE(server.Stop());
+}
+
+// Test that requesting a dump via CrashGenerationClient works
+// Test without actually dumping
+TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ NULL, // dump callback
+ NULL, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ false, // don't generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ CrashGenerationClient client(mach_port_name);
+ bool result = client.RequestDump();
+ exit(result ? 0 : 1);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_TRUE(WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that no minidump was written
+ string pattern = temp_dir.path() + "/*";
+ glob_t dirContents;
+ ret = glob(pattern.c_str(), GLOB_NOSORT, NULL, &dirContents);
+ EXPECT_EQ(GLOB_NOMATCH, ret);
+ if (ret != GLOB_NOMATCH)
+ globfree(&dirContents);
+}
+
+void dumpCallback(void *context, const ClientInfo &client_info,
+ const std::string &file_path) {
+ if (context) {
+ CrashGenerationServerTest* self =
+ reinterpret_cast<CrashGenerationServerTest*>(context);
+ if (!file_path.empty())
+ self->last_dump_name = file_path;
+ self->child_pid = client_info.pid();
+ }
+}
+
+void *RequestDump(void *context) {
+ CrashGenerationClient client((const char*)context);
+ bool result = client.RequestDump();
+ return (void*)(result ? 0 : 1);
+}
+
+// Test that actually writing a minidump works
+TEST_F(CrashGenerationServerTest, testRequestDump) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Have to spawn off a separate thread to request the dump,
+ // because MinidumpGenerator assumes the handler thread is not
+ // the only thread
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, RequestDump, (void*)mach_port_name) != 0)
+ exit(1);
+ void* result;
+ pthread_join(thread, &result);
+ exit(reinterpret_cast<intptr_t>(result));
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_TRUE(WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+ // check client's PID
+ ASSERT_EQ(pid, child_pid);
+}
+
+static void Crasher() {
+ int *a = (int*)0x42;
+
+ fprintf(stdout, "Going to crash...\n");
+ fprintf(stdout, "A = %d", *a);
+}
+
+// Test that crashing a child process with an OOP ExceptionHandler installed
+// results in a minidump being written by the CrashGenerationServer in
+// the parent.
+TEST_F(CrashGenerationServerTest, testChildProcessCrash) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Instantiate an OOP exception handler.
+ ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name);
+ Crasher();
+ // not reached
+ exit(0);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(last_dump_name.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) && \
+ (defined(__x86_64__) || defined(__i386__))
+// Test that crashing a child process of a different architecture
+// produces a valid minidump.
+TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ // Spawn a child process
+ string helper_path = GetHelperPath();
+ const char* argv[] = {
+ helper_path.c_str(),
+ "crash",
+ mach_port_name,
+ NULL
+ };
+ pid_t pid = spawn_child_process(argv);
+ ASSERT_NE(-1, pid);
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+
+const MDCPUArchitecture kExpectedArchitecture =
+#if defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__i386__)
+ MD_CPU_ARCHITECTURE_AMD64
+#endif
+ ;
+const uint32_t kExpectedContext =
+#if defined(__i386__)
+ MD_CONTEXT_AMD64
+#elif defined(__x86_64__)
+ MD_CONTEXT_X86
+#endif
+ ;
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(last_dump_name.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kExpectedArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kExpectedContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(helper_path, main_module->code_file());
+}
+#endif
+
+bool filter_callback(void* context) {
+ CrashGenerationServerTest* self =
+ reinterpret_cast<CrashGenerationServerTest*>(context);
+ self->filter_callback_called = true;
+ // veto dump generation
+ return false;
+}
+
+// Test that a filter callback can veto minidump writing.
+TEST_F(CrashGenerationServerTest, testFilter) {
+ CrashGenerationServer server(mach_port_name,
+ filter_callback, // filter callback
+ this, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Instantiate an OOP exception handler.
+ ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name);
+ Crasher();
+ // not reached
+ exit(0);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+
+ // check that no minidump was written
+ EXPECT_TRUE(last_dump_name.empty());
+ EXPECT_TRUE(filter_callback_called);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
new file mode 100644
index 0000000000..d5b505a1e1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
@@ -0,0 +1,714 @@
+// Copyright (c) 2010, 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.
+
+// exception_handler_test.cc: Unit tests for google_breakpad::ExceptionHandler
+
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/handler/exception_handler.h"
+#include "common/linux/ignore_ret.h"
+#include "common/mac/MachIPC.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using google_breakpad::AutoTempDir;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpMemoryList;
+using google_breakpad::MinidumpMemoryRegion;
+using google_breakpad::ReceivePort;
+using testing::Test;
+
+class ExceptionHandlerTest : public Test {
+ public:
+ void InProcessCrash(bool aborting);
+ AutoTempDir tempDir;
+ string lastDumpName;
+};
+
+static void Crasher() {
+ int *a = (int*)0x42;
+
+ fprintf(stdout, "Going to crash...\n");
+ fprintf(stdout, "A = %d", *a);
+}
+
+static void AbortCrasher() {
+ fprintf(stdout, "Going to crash...\n");
+ abort();
+}
+
+static void SoonToCrash(void(*crasher)()) {
+ crasher();
+}
+
+static bool MDCallback(const char *dump_dir, const char *file_name,
+ void *context, bool success) {
+ string path(dump_dir);
+ path.append("/");
+ path.append(file_name);
+ path.append(".dmp");
+
+ int fd = *reinterpret_cast<int*>(context);
+ IGNORE_RET(write(fd, path.c_str(), path.length() + 1));
+ close(fd);
+ exit(0);
+ // not reached
+ return true;
+}
+
+void ExceptionHandlerTest::InProcessCrash(bool aborting) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+ // Fork off a child process so it can crash.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process.
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // crash
+ SoonToCrash(aborting ? &AbortCrasher : &Crasher);
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+
+ const MDRawExceptionStream* raw_exception = exception->exception();
+ ASSERT_TRUE(raw_exception);
+
+ if (aborting) {
+ EXPECT_EQ(MD_EXCEPTION_MAC_SOFTWARE,
+ raw_exception->exception_record.exception_code);
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_ABORT,
+ raw_exception->exception_record.exception_flags);
+ } else {
+ EXPECT_EQ(MD_EXCEPTION_MAC_BAD_ACCESS,
+ raw_exception->exception_record.exception_code);
+#if defined(__x86_64__)
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS,
+ raw_exception->exception_record.exception_flags);
+#elif defined(__i386__)
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE,
+ raw_exception->exception_record.exception_flags);
+#endif
+ }
+
+ const MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ // Ideally would like to sanity check that abort() is on the stack
+ // but that's hard.
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+}
+
+TEST_F(ExceptionHandlerTest, InProcess) {
+ InProcessCrash(false);
+}
+
+TEST_F(ExceptionHandlerTest, InProcessAbort) {
+ InProcessCrash(true);
+}
+
+static bool DumpNameMDCallback(const char *dump_dir, const char *file_name,
+ void *context, bool success) {
+ ExceptionHandlerTest *self = reinterpret_cast<ExceptionHandlerTest*>(context);
+ if (dump_dir && file_name) {
+ self->lastDumpName = dump_dir;
+ self->lastDumpName += "/";
+ self->lastDumpName += file_name;
+ self->lastDumpName += ".dmp";
+ }
+ return true;
+}
+
+TEST_F(ExceptionHandlerTest, WriteMinidump) {
+ ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true,
+ NULL);
+ ASSERT_TRUE(eh.WriteMinidump());
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // The minidump should not contain an exception stream.
+ Minidump minidump(lastDumpName);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ EXPECT_FALSE(exception);
+}
+
+TEST_F(ExceptionHandlerTest, WriteMinidumpWithException) {
+ ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true,
+ NULL);
+ ASSERT_TRUE(eh.WriteMinidump(true));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // The minidump should contain an exception stream.
+ Minidump minidump(lastDumpName);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+ const MDRawExceptionStream* raw_exception = exception->exception();
+ ASSERT_TRUE(raw_exception);
+
+ EXPECT_EQ(MD_EXCEPTION_MAC_BREAKPOINT,
+ raw_exception->exception_record.exception_code);
+}
+
+TEST_F(ExceptionHandlerTest, DumpChildProcess) {
+ const int kTimeoutMs = 2000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName, "ExceptionHandlerTest.%d", getpid());
+ ReceivePort parent_recv_port(machPortName);
+
+ // Give the child process a pipe to block on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // Fork off a child process to dump.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process
+ close(fds[1]);
+
+ // Send parent process the task and thread ports.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+ child_message.AddDescriptor(mach_thread_self());
+
+ MachPortSender child_sender(machPortName);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS)
+ exit(1);
+
+ // Wait for the parent process.
+ uint8_t data;
+ read(fds[0], &data, 1);
+ exit(0);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[0]);
+
+ // Read the child's task and thread ports.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ mach_port_t child_thread = child_message.GetTranslatedPort(1);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_thread);
+
+ // Write a minidump of the child process.
+ bool result = ExceptionHandler::WriteMinidumpForChild(child_task,
+ child_thread,
+ tempDir.path(),
+ DumpNameMDCallback,
+ this);
+ ASSERT_EQ(true, result);
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Unblock child process
+ uint8_t data = 1;
+ IGNORE_RET(write(fds[1], &data, 1));
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+}
+
+// Test that memory around the instruction pointer is written
+// to the dump as a MinidumpMemoryRegion.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemory) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = kMemorySize / 2;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them in the middle
+ // of the block of memory, because the minidump should contain 128
+ // bytes on either side of the instruction pointer.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kOffset];
+ uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the low end.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = 0;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them at the start
+ // of the block of memory, to ensure that the memory bounding
+ // works properly.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize / 2, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)];
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the high end.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ // Use 4k here because the OS will hand out a single page even
+ // if a smaller size is requested, and this test wants to
+ // test the upper bound of the memory range.
+ const uint32_t kMemorySize = 4096; // bytes
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+ const int kOffset = kMemorySize - sizeof(instructions);
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them at the start
+ // of the block of memory, to ensure that the memory bounding
+ // works properly.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ const size_t kPrefixSize = 128; // bytes
+ EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kPrefixSize];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kPrefixSize,
+ instructions, sizeof(instructions)) == 0);
+}
+
+// Ensure that an extra memory block doesn't get added when the
+// instruction pointer is not in mapped memory.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Try calling a NULL pointer.
+ typedef void (*void_function)(void);
+ // Volatile markings are needed to keep Clang from generating invalid
+ // opcodes. See http://crbug.com/498354 for details.
+ volatile void_function memory_function =
+ reinterpret_cast<void_function>(NULL);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is only one memory region
+ // in the memory list (the thread memory from the single thread).
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_EQ((unsigned int)1, memory_list->region_count());
+}
+
+static void *Junk(void *) {
+ sleep(1000000);
+ return NULL;
+}
+
+// Test that the memory list gets written correctly when multiple
+// threads are running.
+TEST_F(ExceptionHandlerTest, MemoryListMultipleThreads) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+
+ // Run an extra thread so >2 memory regions will be written.
+ pthread_t junk_thread;
+ if (pthread_create(&junk_thread, NULL, Junk, NULL) == 0)
+ pthread_detach(junk_thread);
+
+ // Just crash.
+ Crasher();
+
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump, and verify that the memory list can be read.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+ // Verify that there are three memory regions:
+ // one per thread, and one for the instruction pointer memory.
+ ASSERT_EQ((unsigned int)3, memory_list->region_count());
+}
+
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
new file mode 100644
index 0000000000..b1fa5d02a1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2010, 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.
+
+// minidump_generator_test.cc: Unit tests for google_breakpad::MinidumpGenerator
+
+#include <AvailabilityMacros.h>
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/handler/minidump_generator.h"
+#include "client/mac/tests/spawn_child_process.h"
+#include "common/linux/ignore_ret.h"
+#include "common/mac/MachIPC.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using std::vector;
+using google_breakpad::AutoTempDir;
+using google_breakpad::MinidumpGenerator;
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpModule;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::ReceivePort;
+using testing::Test;
+using namespace google_breakpad_test;
+
+class MinidumpGeneratorTest : public Test {
+ public:
+ AutoTempDir tempDir;
+};
+
+static void *Junk(void* data) {
+ bool* wait = reinterpret_cast<bool*>(data);
+ while (!*wait) {
+ usleep(10000);
+ }
+ return NULL;
+}
+
+TEST_F(MinidumpGeneratorTest, InProcess) {
+ MinidumpGenerator generator;
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+
+ // Run an extra thread since MinidumpGenerator assumes there
+ // are 2 or more threads.
+ pthread_t junk_thread;
+ bool quit = false;
+ ASSERT_EQ(0, pthread_create(&junk_thread, NULL, Junk, &quit));
+
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // join the background thread
+ quit = true;
+ pthread_join(junk_thread, NULL);
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+TEST_F(MinidumpGeneratorTest, OutOfProcess) {
+ const int kTimeoutMs = 2000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName, "MinidumpGeneratorTest.OutOfProcess.%d", getpid());
+ ReceivePort parent_recv_port(machPortName);
+
+ // Give the child process a pipe to block on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // Fork off a child process to dump.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process
+ close(fds[1]);
+
+ // Send parent process the task port.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+
+ MachPortSender child_sender(machPortName);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS) {
+ fprintf(stderr, "Error sending message from child process!\n");
+ exit(1);
+ }
+
+ // Wait for the parent process.
+ uint8_t data;
+ read(fds[0], &data, 1);
+ exit(0);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[0]);
+
+ // Read the child's task port.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+
+ // Write a minidump of the child process.
+ MinidumpGenerator generator(child_task, MACH_PORT_NULL);
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Unblock child process
+ uint8_t data = 1;
+ IGNORE_RET(write(fds[1], &data, 1));
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+// This test fails on 10.5, but I don't have easy access to a 10.5 machine,
+// so it's simpler to just limit it to 10.6 for now.
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) && \
+ (defined(__x86_64__) || defined(__i386__))
+
+TEST_F(MinidumpGeneratorTest, CrossArchitectureDump) {
+ const int kTimeoutMs = 5000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName,
+ "MinidumpGeneratorTest.CrossArchitectureDump.%d", getpid());
+
+ ReceivePort parent_recv_port(machPortName);
+
+ // Spawn a child process to dump.
+ string helper_path = GetHelperPath();
+ const char* argv[] = {
+ helper_path.c_str(),
+ machPortName,
+ NULL
+ };
+ pid_t pid = spawn_child_process(argv);
+ ASSERT_NE(-1, pid);
+
+ // Read the child's task port.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+
+ // Write a minidump of the child process.
+ MinidumpGenerator generator(child_task, MACH_PORT_NULL);
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Kill child process.
+ kill(pid, SIGKILL);
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+
+const MDCPUArchitecture kExpectedArchitecture =
+#if defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__i386__)
+ MD_CPU_ARCHITECTURE_AMD64
+#endif
+ ;
+const uint32_t kExpectedContext =
+#if defined(__i386__)
+ MD_CONTEXT_AMD64
+#elif defined(__x86_64__)
+ MD_CONTEXT_X86
+#endif
+ ;
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kExpectedArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kExpectedContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(helper_path, main_module->code_file());
+}
+#endif // 10.6 && (x86-64 || i386)
+
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc
new file mode 100644
index 0000000000..4e8ce3cf00
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010, 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.
+
+// minidump_generator_test_helper.cc: A helper program that
+// minidump_generator_test.cc can launch to test certain things
+// that require a separate executable.
+
+#include <unistd.h>
+
+#include "client/mac/handler/exception_handler.h"
+#include "common/mac/MachIPC.h"
+
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::ReceivePort;
+
+int main(int argc, char** argv) {
+ if (argc < 2)
+ return 1;
+
+ if (strcmp(argv[1], "crash") != 0) {
+ const int kTimeoutMs = 2000;
+ // Send parent process the task and thread ports.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+ child_message.AddDescriptor(mach_thread_self());
+
+ MachPortSender child_sender(argv[1]);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS) {
+ fprintf(stderr, "Error sending message from child process!\n");
+ exit(1);
+ }
+
+ // Loop forever.
+ while (true) {
+ sleep(100);
+ }
+ } else if (argc == 3 && strcmp(argv[1], "crash") == 0) {
+ // Instantiate an OOP exception handler
+ google_breakpad::ExceptionHandler eh("", NULL, NULL, NULL, true, argv[2]);
+ // and crash.
+ int *a = (int*)0x42;
+ *a = 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h b/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h
new file mode 100644
index 0000000000..1b82c56278
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2010, 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.
+
+// Utility functions for spawning a helper process using a different
+// CPU architecture.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
+#define GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
+
+#include <AvailabilityMacros.h>
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+#include <crt_externs.h>
+#include <mach-o/dyld.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#include <spawn.h>
+#endif
+
+#include <string>
+#include <vector>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad_test {
+
+using std::string;
+using std::vector;
+
+const MDCPUArchitecture kNativeArchitecture =
+#if defined(__i386__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_AMD64
+#elif defined(__ppc__) || defined(__ppc64__)
+ MD_CPU_ARCHITECTURE_PPC
+#else
+#error "This file has not been ported to this CPU architecture."
+#endif
+ ;
+
+const uint32_t kNativeContext =
+#if defined(__i386__)
+ MD_CONTEXT_X86
+#elif defined(__x86_64__)
+ MD_CONTEXT_AMD64
+#elif defined(__ppc__) || defined(__ppc64__)
+ MD_CONTEXT_PPC
+#else
+#error "This file has not been ported to this CPU architecture."
+#endif
+ ;
+
+string GetExecutablePath() {
+ char self_path[PATH_MAX];
+ uint32_t size = sizeof(self_path);
+ if (_NSGetExecutablePath(self_path, &size) != 0)
+ return "";
+ return self_path;
+}
+
+string GetHelperPath() {
+ string helper_path(GetExecutablePath());
+ size_t pos = helper_path.rfind('/');
+ if (pos == string::npos)
+ return "";
+
+ helper_path.erase(pos + 1);
+ helper_path += "minidump_generator_test_helper";
+ return helper_path;
+}
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+
+pid_t spawn_child_process(const char** argv) {
+ posix_spawnattr_t spawnattr;
+ if (posix_spawnattr_init(&spawnattr) != 0)
+ return (pid_t)-1;
+
+ cpu_type_t pref_cpu_types[2] = {
+#if defined(__x86_64__)
+ CPU_TYPE_X86,
+#elif defined(__i386__)
+ CPU_TYPE_X86_64,
+#endif
+ CPU_TYPE_ANY
+ };
+
+ // Set spawn attributes.
+ size_t attr_count = sizeof(pref_cpu_types) / sizeof(pref_cpu_types[0]);
+ size_t attr_ocount = 0;
+ if (posix_spawnattr_setbinpref_np(&spawnattr,
+ attr_count,
+ pref_cpu_types,
+ &attr_ocount) != 0 ||
+ attr_ocount != attr_count) {
+ posix_spawnattr_destroy(&spawnattr);
+ return (pid_t)-1;
+ }
+
+ // Create an argv array.
+ vector<char*> argv_v;
+ while (*argv) {
+ argv_v.push_back(strdup(*argv));
+ argv++;
+ }
+ argv_v.push_back(NULL);
+ pid_t new_pid = 0;
+ int result = posix_spawnp(&new_pid, argv_v[0], NULL, &spawnattr,
+ &argv_v[0], *_NSGetEnviron());
+ posix_spawnattr_destroy(&spawnattr);
+
+ for (unsigned i = 0; i < argv_v.size(); i++) {
+ free(argv_v[i]);
+ }
+
+ return result == 0 ? new_pid : -1;
+}
+#endif
+
+} // namespace google_breakpad_test
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h b/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h
new file mode 100644
index 0000000000..c6b6be699b
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h
@@ -0,0 +1,9 @@
+// This file exists to override the processor logging for unit tests,
+// since it confuses XCode into thinking unit tests have failed.
+#include <sstream>
+
+namespace google_breakpad {
+extern std::ostringstream info_log;
+}
+
+#define BPLOG_INFO_STREAM google_breakpad::info_log